Changeset 88 for branches

Show
Ignore:
Timestamp:
06/05/07 09:10:00 (5 years ago)
Author:
apdavison
Message:

Merged changes r84:87 from trunk

Location:
branches/connector-class
Files:
7 modified

Legend:

Unmodified
Added
Removed
  • branches/connector-class/facetsml.py

    r49 r88  
    1111from xml.dom.ext import * 
    1212 
    13          
    14 open_files = [] 
    15  
    16 dt = 0.1 
     13gid           = 0 
     14ncid          = 0 
     15gidlist       = [] 
     16vfilelist     = {} 
     17spikefilelist = {} 
     18dt            = 0.1 
     19running       = False 
     20 
     21# ============================================================================== 
     22#   Module-specific functions and classes (not part of the common API) 
     23# ============================================================================== 
     24 
     25 
    1726xmldoc = Document() 
    1827 
     
    6877 
    6978# ============================================================================== 
    70 #   Module-specific functions and classes (not part of the common API) 
    71 # ============================================================================== 
    72  
    73 class StandardCells: # do we need this? The FACETS-ML names and the PyNN names should be the same 
    74     """ 
    75     This is a static class which which contains one method for each of the 
    76     standard FACETS cell models. Each method: 
    77       (i) has a .nest_name attribute which is the NEST-specific name for the model 
    78       (ii) takes a dictionary whose keys are the standard parameter names 
    79       (iii) returns a dictionary whose keys are the NEST-specific parameter 
    80          names. This dictionary also contains any extra, NEST-only parameters. 
    81     """ 
    82      
    83     def IF_curr_alpha(parameterDict): 
    84         """ 
    85         Integrate-and-fire cell with alpha-shaped post-synaptic current. 
    86          
    87         The keys in parameterDict must come from this list: 
    88           'vrest', 'cm', 'tau_m', 'tau_refrac', 'tau_syn', 'v_thresh' 
    89         Units: v* (mV), cm (nF), tau* (ms) 
    90         Any required parameters not in parameterDict will be given default values. 
    91          
    92         Returns a parameter dictionary with NEST-specific parameter names. 
    93         """ 
    94         global dt 
    95          
    96         parameters = common.default_values['IF_curr_alpha'] 
    97         if parameterDict: 
    98             for k in parameters.keys(): 
    99                 if parameterDict.has_key(k): 
    100                     parameters[k] = parameterDict[k] 
    101         if parameters['v_reset'] != parameters['v_rest']: 
    102             raise "It is not possible to make v_reset different from v_rest in iaf_neuron." 
    103         translated_parameters = { 
    104             'U0'         : parameters['v_rest'], 
    105             'C'          : parameters['cm']*1000.0, # C is in pF, cm in nF 
    106             'Tau'        : parameters['tau_m'], 
    107             'TauR'       : max(dt,parameters['tau_refrac']), 
    108             'TauSyn'     : parameters['tau_syn'], 
    109             'Theta'      : parameters['v_thresh'], 
    110             'I0'         : parameters['i_offset']*1000.0, # I0 is in pA, i_offset in nA 
    111             'LowerBound' : -1000.0 } 
    112         return translated_parameters 
    113       
    114     def SpikeSourcePoisson(parameterDict): 
    115         """ 
    116         Spike source, generating spikes according to a Poisson process. 
    117          
    118         The keys in parameterDict must come from this list: 
    119           'rate', 'start', 'duration' 
    120         Units: rate (Hz), start (ms), duration (ms) 
    121         Any required parameters not in parameterDict will be given default values. 
    122          
    123         Returns a parameter dictionary with NEST-specific parameter names 
    124         """ 
    125          
    126         parameters = common.default_values['SpikeSourcePoisson'] 
    127         if parameterDict: 
    128             for k in parameters.keys(): 
    129                 if parameterDict.has_key(k): 
    130                     parameters[k] = parameterDict[k] 
    131         translated_parameters = { 
    132             'rate'     : parameters['rate'], 
    133             'start'    : parameters['start'], 
    134             'duration' : parameters['duration'], 
    135             'origin'   : 1.0 } 
    136         return translated_parameters    
    137      
    138     def SpikeSourceArray(parameterDict): 
    139         """ 
    140         Spike source generating spikes at the times given in the spike_times array. 
    141          
    142         parameterDict must contain this key: spike_times, whose value should be 
    143         a list or numpy array containing spike times in milliseconds. 
    144  
    145         Returns a parameter dictionary with NEST-specific parameter names 
    146         """ 
    147         parameters = common.default_values['SpikeSourceArray'] 
    148         for k in parameters.keys(): 
    149             if parameterDict.has_key(k): 
    150                 parameters[k] = parameterDict[k] 
    151         translated_parameters = { 
    152             'spike_times' : parameters['spike_times'] 
    153         } 
    154         return translated_parameters 
    155              
    156      
    157     setattr(IF_curr_alpha,'nest_name','iaf_neuron') 
    158     setattr(SpikeSourcePoisson,'nest_name','poisson_generator') 
    159     setattr(SpikeSourceArray,'nest_name','spike_generator') 
    160     IF_curr_alpha = staticmethod(IF_curr_alpha) 
    161     SpikeSourcePoisson = staticmethod(SpikeSourcePoisson) 
    162     SpikeSourceArray = staticmethod(SpikeSourceArray) 
     79#   Utility classes 
     80# ============================================================================== 
     81 
     82class ID(common.ID): 
     83    """ 
     84    This class is experimental. The idea is that instead of storing ids as 
     85    integers, we store them as ID objects, which allows a syntax like: 
     86      p[3,4].set('tau_m',20.0) 
     87    where p is a Population object. The question is, how big a memory/performance 
     88    hit is it to replace integers with ID objects? 
     89    """ 
     90     
     91    def set(self,param,val=None): 
     92        # We perform a call to the low-level function set() of the API. 
     93        # If the cellclass is not defined in the ID object, we have an error (?) : 
     94        if (self._cellclass == None): 
     95            raise Exception("Unknown cellclass") 
     96        else: 
     97            #Otherwise we use the ID one. Nevertheless, here we have a small problem in the 
     98            #parallel framework. Suppose a population is created, distributed among 
     99            #several nodes. Then a call like cell[i,j].set() should be performed only on the 
     100            #node who owns the cell. To do that, if the node doesn't have the cell, a call to set() 
     101            #do nothing... 
     102            ##if self._hocname != None: 
     103            ##    set(self,self._cellclass,param,val, self._hocname) 
     104            set(self,self._cellclass,param,val) 
     105     
     106    def get(self,param): 
     107        #This function should be improved, with some test to translate 
     108        #the parameter according to the cellclass 
     109        #We have here the same problem as with set() in the parallel framework 
     110        if self._hocname != None: 
     111            return HocToPy.get('%s.%s' %(self._hocname, param),'float') 
     112     
     113    # Fonctions used only by the neuron version of pyNN, to optimize the 
     114    # creation of networks 
     115    def setHocName(self, name): 
     116        self._hocname = name 
     117 
     118    def getHocName(self): 
     119        return self._hocname 
     120 
     121 
     122def checkParams(param,val=None): 
     123    """Check parameters are of valid types, normalise the different ways of 
     124       specifying parameters and values by putting everything in a dict. 
     125       Called by set() and Population.set().""" 
     126    if isinstance(param,str): 
     127        if isinstance(val,float) or isinstance(val,int): 
     128            paramDict = {param:float(val)} 
     129        elif isinstance(val,(str, list)): 
     130            paramDict = {param:val} 
     131        else: 
     132            raise common.InvalidParameterValueError 
     133    elif isinstance(param,dict): 
     134        paramDict = param 
     135    else: 
     136        raise common.InvalidParameterValueError 
     137    return paramDict 
     138 
     139 
     140# ============================================================================== 
     141#   Standard cells 
     142# ============================================================================== 
     143 
     144""" 
     145As I don't really care about which CellClass is it, as I will dump its parameters 
     146"as it" in XML, all my CellType are a wrapper around a FacetsmlCellType 
     147The creation of default parameters is done in the common constructors 
     148""" 
     149 
     150class FacetsmlCellType(object): 
     151    """Base class for facetsMLCellType""" 
     152     
     153    def __init__(self,facetsml_name,parameters): 
     154        cellsNode = initDocument('http://morphml.org/neuroml/schema','cells') 
     155        cellNode = xmldoc.createElementNS('http://morphml.org/neuroml/schema','cell') 
     156        self.domNode = cellNode 
     157        cellsNode.appendChild(cellNode) 
     158        facetsml_nameNode = xmldoc.createElementNS('http://morphml.org/neuroml/schema',facetsml_name) 
     159        # just dump "as it" the given parameters 
     160        for k in self.parameters.keys: 
     161            facetsml_nameNode.setAttribute(k,self.parameters[k]) 
     162        cellNode.appendChild(facetsml_nameNode) 
     163 
     164 
     165class StandardCellType(common.StandardCellType): 
     166    """Base class for standardized cell model classes.""" 
     167     
     168    facetsml_name = "StandardCellType" 
     169 
     170    def __init__(self,parameters): 
     171        common.StandardCellType.__init__(self,parameters) 
     172        self.facetsmlCellType = FacetsmlCellType(facetsml_name,self.parameters) 
     173 
     174     
     175class IF_curr_alpha(common.IF_curr_alpha): 
     176    """Leaky integrate and fire model with fixed threshold and alpha-function- 
     177    shaped post-synaptic current.""" 
     178 
     179    facetsml_name = "IF_curr_alpha" 
     180 
     181    def __init__(self,parameters): 
     182        common.IF_curr_alpha.__init__(self,parameters) 
     183        self.facetsmlCellType = FacetsmlCellType(facetsml_name,self.parameters) 
     184     
     185 
     186class IF_curr_exp(common.IF_curr_exp): 
     187    """Leaky integrate and fire model with fixed threshold and 
     188    decaying-exponential post-synaptic current. (Separate synaptic currents for 
     189    excitatory and inhibitory synapses""" 
     190     
     191    facetsml_name = "IF_curr_exp" 
     192 
     193    def __init__(self,parameters): 
     194        common.IF_curr_exp.__init__(self,parameters) 
     195        self.facetsmlCellType = FacetsmlCellType(facetsml_name,self.parameters) 
     196     
     197 
     198class IF_cond_alpha(common.IF_cond_alpha): 
     199    """Leaky integrate and fire model with fixed threshold and alpha-function- 
     200    shaped post-synaptic conductance.""" 
     201     
     202    facetsml_name = "IF_cond_alpha" 
     203 
     204    def __init__(self,parameters): 
     205        common.IF_cond_alpha.__init__(self,parameters) 
     206        self.facetsmlCellType = FacetsmlCellType(facetsml_name,self.parameters) 
     207 
     208class SpikeSourcePoisson(common.SpikeSourcePoisson): 
     209    """Spike source, generating spikes according to a Poisson process.""" 
     210 
     211    facetsml_name = "SpikeSourcePoisson" 
     212 
     213    def __init__(self,parameters): 
     214        common.SpikeSourcePoisson.__init__(self,parameters) 
     215        self.facetsmlCellType = FacetsmlCellType(facetsml_name,self.parameters) 
     216 
     217class SpikeSourceArray(common.SpikeSourceArray): 
     218    """Spike source generating spikes at the times given in the spike_times array.""" 
     219 
     220    facetsml_name = "SpikeSourceArray" 
     221 
     222    def __init__(self,parameters): 
     223        common.SpikeSourceArray.__init__(self,parameters) 
     224        self.facetsmlCellType = FacetsmlCellType(facetsml_name,self.parameters) 
     225 
     226 
    163227 
    164228# ============================================================================== 
     
    173237 
    174238def end(): 
    175     """Do any necessary cleaning up before exiting.""" 
    176     raise "Not yet implemented" 
     239    PrettyPrint(xmldoc) 
    177240 
    178241def run(simtime): 
    179     """Run the simulation for simtime ms.""" 
    180     raise "Not yet implemented" 
     242    PrettyPrint(xmldoc) 
    181243 
    182244def setRNGseeds(seedList): 
     
    195257    If n==1, return just the single id. 
    196258    """ 
     259    global gid, gidlist, nhost, myid 
     260     
    197261    assert n > 0, 'n must be a positive integer' 
    198     translate = getattr(StandardCells,celltype)     
    199     cell_ids = None 
    200     raise "Not yet implemented" 
     262    #must look if the cellclass is not already defined 
     263     
     264    if isinstance(cellclass, type): 
     265        celltype = cellclass(paramDict) 
     266    elif isinstance(cellclass,str): 
     267        #define a new cellType 
     268        celltype = FacetsmlCellType(cellclass,paramDict) 
     269  
     270    # round-robin partitioning 
     271    newgidlist = [i+myid for i in range(gid,gid+n,nhost) if i < gid+n-myid] 
     272    for cell_id in newgidlist: 
     273        celltype.domNode.setAttribute("name",'cell%d' % cell_id) 
     274     
     275    gidlist.extend(newgidlist) 
     276    cell_list = range(gid,gid+n) 
     277    gid = gid+n 
    201278    if n == 1: 
    202         return cell_ids[0] 
    203     else: 
    204         return cell_ids 
    205  
    206 def connect(source,target,weight=None,delay=None,p=1): 
     279        cell_list = cell_list[0] 
     280    return cell_list 
     281 
     282def connect(source,target,weight=None,delay=None,synapse_type=None,p=1,rng=None): 
    207283    """Connect a source of spikes to a synaptic target. source and target can 
    208284    both be individual cells or lists of cells, in which case all possible 
    209     connections are made with probability p.""" 
    210     global dt 
    211     if weight is None: 
    212         weight = 0.0 
    213     if delay is None: 
    214         delay = dt 
    215     if type(source) != types.ListType and type(target) != types.ListType: 
    216         connect_id = None 
    217     else: 
    218         connect_id = [] 
    219         if type(source) != types.ListType: 
    220             source = [source] 
    221         if type(target) != types.ListType: 
    222             target = [target] 
    223         for src in source: 
    224             src = pynest.getAddress(src) 
    225             for tgt in target: 
    226                 tgt = pynest.getAddress(tgt) 
    227                 if int(p) == 1 or RandomArray.uniform(0,1)<p: 
    228                     connect_id += [None] 
    229     raise "Not yet implemented" 
    230     return connect_id 
    231  
    232 def set(cells,celltype,param,val=None): 
     285    connections are made with probability p, using either the random number 
     286    generator supplied, or the default rng otherwise. 
     287    Weights should be in nA or uS.""" 
     288    raise Exception("Method not yet implemented") 
     289 
     290 
     291def set(cells,cellclass,param,val=None): 
    233292    """Set one or more parameters of an individual cell or list of cells. 
    234293    param can be a dict, in which case val should not be supplied, or a string 
    235294    giving the parameter name, in which case val is the parameter value. 
    236     celltype must be supplied for doing translation of parameter names.""" 
    237     translate = getattr(StandardCells,celltype)  
    238     if val: 
    239         param = {param:val} 
    240     if type(cells) != types.ListType: 
    241         cells = [cells] 
    242     raise "Not yet implemented" 
    243  
    244 def record(src,filename): 
    245     """Record spikes to a file. src can be an individual cell or a list of 
    246     cells.""" 
    247     # would actually like to be able to record to an array and choose later 
    248     # whether to write to a file. 
    249     raise "Function not yet implemented." 
    250  
    251 def record_v(source,filename): 
    252     """ 
    253     Record membrane potential to a file. source can be an individual cell or 
    254     a list of cells.""" 
    255     # would actually like to be able to record to an array and 
    256     # choose later whether to write to a file. 
    257     if type(source) == types.ListType: 
    258         source = [pynest.getAddress(src) for src in source] 
    259     else: 
    260         source = [pynest.getAddress(source)] 
    261     for src in source: 
    262         None 
    263     raise "Function not yet implemented." 
    264      
     295    cellclass must be supplied for doing translation of parameter names.""" 
     296    raise Exception("Method not yet implemented") 
     297 
    265298 
    266299# ============================================================================== 
     
    273306    An array of neurons all of the same type. `Population' is used as a generic 
    274307    term intended to include layers, columns, nuclei, etc., of cells. 
     308    All cells have both an address (a tuple) and an id (an integer). If p is a 
     309    Population object, the address and id can be inter-converted using : 
     310    id = p[address] 
     311    address = p.locate(id) 
    275312    """ 
    276313    nPop = 0 
     
    281318          integer, for a one-dimensional population. 
    282319          e.g., (10,10) will create a two-dimensional population of size 10x10. 
    283         celltype should be a string - the name of the neuron model class that 
    284           makes up the population. 
     320        cellclass should either be a standardized cell class (a class inheriting 
     321        from common.StandardCellType) or a string giving the name of the 
     322        simulator-specific model that makes up the population. 
    285323        cellparams should be a dict which is passed to the neuron model 
    286324          constructor 
    287325        label is an optional name for the population. 
    288      
    289     example of NeuroML (completeNetwork.xml with CellGroupC example added) : 
    290     <net:populations> 
    291         <net:population name="CellGroupA"> 
    292             <net:cell_type>CellA</net:cell_type> 
    293             <net:instances> 
    294                 <net:instance id="0"><net:location x="0" y="0" z="0"/></net:instance> 
    295                 <net:instance id="1"><net:location x="0" y="10" z="0"/></net:instance> 
    296                 <net:instance id="2"><net:location x="0" y="20" z="0"/></net:instance> 
    297             </net:instances> 
    298         </net:population> 
    299         <net:population name="CellGroupB"> 
    300             <net:cell_type>CellA</net:cell_type> 
    301             <net:instances> 
    302                 <net:instance id="0"><net:location x="0" y="100" z="0"/></net:instance> 
    303                 <net:instance id="1"><net:location x="20" y="100" z="0"/></net:instance> 
    304             </net:instances> 
    305         </net:population> 
    306         <net:population name="CellGroupC"> 
    307             <net:cell_type>CellC</net:cell_type> 
    308             <net:pop_location reference="aeag"> 
    309                 <net:grid_arrangement> 
    310                     <net:rectangular_location name="aefku"> 
    311                         <meta:corner x="0" y="0" z="0"/> 
    312                         <meta:size depth="10" height="100" width="100"/> 
    313                     </net:rectangular_location> 
    314                     <net:spacing x="10" y="10" z="10"/> 
    315                 </net:grid_arrangement> 
    316             </net:pop_location> 
    317         </net:population> 
    318     </net:populations> 
    319      
    320         """ 
     326        """ 
     327        global gid, myid, nhost, gidlist, fullgidlist 
    321328         
    322329        common.Population.__init__(self,dims,cellclass,cellparams,label) 
    323                       
    324          
    325         if not self.label: 
     330        #if self.ndim > 1: 
     331        #    for i in range(1,self.ndim): 
     332        #        if self.dim[i] != self.dim[0]: 
     333        #            raise common.InvalidDimensionsError, "All dimensions must be the same size (temporary restriction)." 
     334 
     335        # set the steps list, used by the __getitem__() method. 
     336        self.steps = [1]*self.ndim 
     337        for i in xrange(self.ndim-1): 
     338            for j in range(i+1,self.ndim): 
     339                self.steps[i] *= self.dim[j] 
     340 
     341        if isinstance(cellclass, type): 
     342            #maybe we should look if the cellclass is not already defined 
     343            self.celltype = cellclass(cellparams) 
     344            self.cellparams = self.celltype.parameters 
     345            #not used ? 
     346            facetsml_name = self.celltype.facetsml_name 
     347        elif isinstance(cellclass, str): # not a standard model 
     348            #define a new cellType 
     349            self.celltype = FacetsmlCellType(cellclass,paramDict) 
     350         
     351         
     352        if not self.label: 
    326353            self.label = 'population%d' % Population.nPop 
    327      
    328      
     354         
     355         
     356        #the <population> markup is linked, in NeuroML, to a <cell> markup, which defines the type of cells of the population 
     357        # the cell_type name which makes the link is here the concatenation of 'cell_type_' and population label 
     358        cell_type_label = 'cell_type_%s' % label 
     359        self.celltype.domNode. = setAttribute("name",'cell_type_%s' % label) 
     360         
     361         
     362        # Now the gid and cellclass are stored as instance of the ID class, which will allow a syntax like 
     363        # p[i,j].set(param, val). But we have also to deal with positions : a population needs to know ALL the positions 
     364        # of its cells, and not only those of the cells located on a particular node (i.e in self.gidlist). So 
     365        # each population should store what we call a "fullgidlist" with the ID of all the cells in the populations  
     366        # (and therefore their positions) 
     367        self.fullgidlist = [ID(i) for i in range(gid, gid+self.size) if i < gid+self.size] 
     368         
     369        # self.gidlist is now derived from self.fullgidlist since it contains only the cells of the population located on 
     370        # the node 
     371        self.gidlist     = [self.fullgidlist[i+myid] for i in range(0, len(self.fullgidlist),nhost) if i < len(self.fullgidlist)-myid] 
     372        self.gid_start   = gid 
     373 
     374         
     375             
    329376        populationsNode = initDocument('http://morphml.org/networkml/schema','populations','net') 
    330377     
     
    332379        populationNode.setAttribute('name',label) 
    333380        populationsNode.appendChild(populationNode) 
     381        self.dom_node = populationNode 
    334382     
    335383        cell_typeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','net:cell_type') 
    336         #coming from neuron.py 
    337         if isinstance(cellclass, type): 
    338             self.celltype = cellclass(cellparams) 
    339             self.cellparams = self.celltype.parameters 
    340             hoc_name = self.celltype.hoc_name 
    341         elif isinstance(cellclass, str): # not a standard model 
    342             hoc_name = cellclass 
    343         #end of coming 
    344          
    345         cell_typeTextNode = xmldoc.createTextNode(hoc_name) 
     384        cell_typeTextNode = xmldoc.createTextNode(cell_type_label) 
    346385        cell_typeNode.appendChild(cell_typeTextNode) 
    347386        populationNode.appendChild(cell_typeNode) 
    348         """ 
     387         
     388         
     389             
     390         """ 
    349391        the minimal neuroml to add there is : 
    350392        <net:pop_location reference="aReference"> 
     
    391433        grid_arrangementNode.appendChild(spacingNode) 
    392434         
    393          
    394         #cellparams would be defined in a <cell> markup which would define precisely the neuron model 
    395          
    396          
    397         #raise "Not yet implemented." 
    398          
    399          
     435     
    400436        Population.nPop += 1 
     437        gid = gid+self.size 
     438 
     439        # We add the gidlist of the population to the global gidlist 
     440        gidlist += self.gidlist 
     441         
     442        # By default, the positions of the cells are their coordinates, given by the locate() 
     443        # method. Note that each node needs to know all the positions of all the cells  
     444        # in the population 
     445        for cell_id in self.fullgidlist: 
     446            cell_id.setCellClass(cellclass) 
     447            cell_id.setPosition(self.locate(cell_id)) 
     448                     
     449         
    401450        PrettyPrint(xmldoc) 
    402      
    403          
    404     def set(self,param,val): 
     451 
     452         
     453    def __getitem__(self,addr): 
     454        """Returns a representation of the cell with coordinates given by addr, 
     455           suitable for being passed to other methods that require a cell id. 
     456           Note that __getitem__ is called when using [] access, e.g. 
     457             p = Population(...) 
     458             p[2,3] is equivalent to p.__getitem__((2,3)). 
     459        """ 
     460 
     461        global gidlist 
     462 
     463        # What we actually pass around are gids. 
     464        if isinstance(addr,int): 
     465            addr = (addr,) 
     466        if len(addr) != len(self.dim): 
     467            raise common.InvalidDimensionsError, "Population has %d dimensions. Address was %s" % (self.ndim,str(addr)) 
     468        index = 0 
     469        for i,s in zip(addr,self.steps): 
     470            index += i*s 
     471        id = index + self.gid_start 
     472        assert addr == self.locate(id), 'index=%s addr=%s id=%s locate(id)=%s' % (index, addr, id, self.locate(id)) 
     473        # We return the gid as an ID object. Note that each instance of Populations 
     474        # distributed on several node can give the ID object, because fullgidlist is duplicated 
     475        # and common to all the node (not the case of global gidlist, or self.gidlist) 
     476        return self.fullgidlist[index] 
     477 
     478         
     479    def locate(self,id): 
     480        """Given an element id in a Population, return the coordinates. 
     481               e.g. for  4 6  , element 2 has coordinates (1,0) and value 7 
     482                         7 9 
     483        """ 
     484        # id should be a gid 
     485        assert isinstance(id,int), "id is %s, not int" % type(id) 
     486        id -= self.gid_start 
     487        if self.ndim == 3: 
     488            rows = self.dim[1]; cols = self.dim[2] 
     489            i = id/(rows*cols); remainder = id%(rows*cols) 
     490            j = remainder/cols; k = remainder%cols 
     491            coords = (i,j,k) 
     492        elif self.ndim == 2: 
     493            cols = self.dim[1] 
     494            i = id/cols; j = id%cols 
     495            coords = (i,j) 
     496        elif self.ndim == 1: 
     497            coords = (id,) 
     498        else: 
     499            raise common.InvalidDimensionsError 
     500        return coords 
     501         
     502         
     503    def set(self,param,val=None): 
    405504        """ 
    406505        Set one or more parameters for every cell in the population. param 
    407506        can be a dict, in which case val should not be supplied, or a string 
    408507        giving the parameter name, in which case val is the parameter value. 
    409         e.g. p.set("tau",20.0). 
    410              p.set({'tau':20,'v_rest':-65}) 
    411         """ 
    412         raise "Method not yet implemented." 
     508        val can be a numeric value, or list of such (e.g. for setting spike times). 
     509        e.g. p.set("tau_m",20.0). 
     510             p.set({'tau_m':20,'v_rest':-65}) 
     511        """ 
     512        paramDict = checkParams(param,val) 
     513 
     514        for param,val in paramDict.items(): 
     515            if isinstance(val,str): 
     516                #I have to retrieve the <cell> markup which defines the type of cells of that population 
     517                # self.cellType is the cellType class, which contains the corresponding domNode 
     518                # self.cellType.facetsml_name, for example "IF_curr_alpha" is the name of the markup under <cell> 
     519                cellTypeNode = self.cellType.domNode.getElementsByTagNameNS('http://morphml.org/neuroml/schema',self.celltype.facetsml_name) 
     520                cellTypeNode.setAttribute(param,val) 
     521 
     522 
    413523         
    414524    def tset(self,parametername,valueArray): 
     
    417527        valueArray, which must have the same dimensions as the Population. 
    418528        """ 
    419         raise "Method not yet implemented" 
    420      
    421     def rset(self,parametername,randomobj): 
     529        raise Exception("not yet implemented") 
     530     
     531    def rset(self,parametername,rand_distr): 
    422532        """ 
    423533        'Random' set. Sets the value of parametername to a value taken from 
    424         the randomobj Random object. 
    425         """ 
    426         raise "Method not yet implemented" 
    427      
    428     def call(self,methodname,arguments): 
    429         """ 
    430         Calls the method methodname(arguments) for every cell in the population. 
    431         e.g. p.call("set_background","0.1") if the cell class has a method 
    432         set_background(). 
    433         """ 
    434         raise "Method not yet implemented" 
    435      
    436     def tcall(self,methodname,objarr): 
    437         """ 
    438         `Topographic' call. Calls the method methodname() for every cell in the  
    439         population. The argument to the method depends on the coordinates of the 
    440         cell. objarr is an array with the same dimensions as the Population. 
    441         e.g. p.tcall("memb_init",vinitArray) calls 
    442         p.cell[i][j].memb_init(vInitArray[i][j]) for all i,j. 
    443         """ 
    444         raise "Method not yet implemented" 
    445  
    446     def record(self,record_from=None): 
    447         """ 
    448         If record_from is not given, record spikes from all cells in the Population. 
    449         record_from can be an integer - the number of cells to record from, chosen 
    450         at random - or a list containing the ids (e.g., (i,j,k) tuple for a 3D 
    451         population) of the cells to record. 
    452         """ 
    453         raise "Method not yet implemented" 
    454  
    455     def record_v(self,record_from=None): 
    456         """ 
    457         If record_from is not given, record the membrane potential for all cells in 
    458         the Population. 
    459         record_from can be an integer - the number of cells to record from, chosen 
    460         at random - or a list containing the ids (e.g., (i,j,k) tuple for a 3D 
    461         population) of the cells to record. 
    462         """ 
    463         raise "Method not yet implemented" 
    464      
    465      
    466     def printSpikes(self,filename): 
    467         """ 
    468         Prints spike times to file in the two-column format 
    469         "spiketime cell_id" where cell_id is the index of the cell counting 
    470         along rows and down columns (and the extension of that for 3-D). 
    471         This allows easy plotting of a `raster' plot of spiketimes, with one 
    472         line for each cell. 
    473         """ 
    474         raise "Method not yet implemented" 
    475  
    476     def meanSpikeCount(self): 
    477         """ 
    478         Returns the mean number of spikes per neuron. 
    479         """ 
    480         raise "Method not yet implemented" 
    481  
    482     def randomInit(self,randobj): 
     534        rand_distr, which should be a RandomDistribution object. 
     535        """ 
     536        raise Exception("not yet implemented") 
     537 
     538 
     539    def randomInit(self,rand_distr): 
    483540        """ 
    484541        Sets initial membrane potentials for all the cells in the population to 
    485542        random values. 
    486543        """ 
    487         raise "Method not yet implemented" 
    488      
    489     def print_v(self,filename): 
    490         """ 
    491         Write membrane potential traces to file. Assumes that the cell class 
    492         defines an array vrecord that is used to record membrane potential. 
    493         """ 
    494         raise "Method not yet implemented" 
    495          
     544        raise Exception("not yet implemented") 
     545     
     546 
    496547     
    497548class Projection(common.Projection): 
     
    570621        self._targets = [] 
    571622        self._sources = [] 
    572         #connection_method = getattr(self,'_%s' % method) 
    573         #self.nconn = connection_method(methodParameters) 
    574          
    575          
    576          
    577          
    578          
    579623         
    580624        projectionsNode = initDocument('http://morphml.org/networkml/schema','projections') 
     
    584628        projectionNode.setAttribute('name',label) 
    585629        projectionsNode.appendChild(projectionNode) 
     630        self.domNode = projectionNode 
    586631         
    587632        sourceNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','source') 
     
    606651            postsynaptic_populationName = postsynaptic_population 
    607652         
    608          
    609653        targetTextNode = xmldoc.createTextNode(postsynaptic_populationName) 
    610654        targetNode.appendChild(targetTextNode) 
    611655        projectionNode.appendChild(targetNode) 
    612656         
    613         synapse_propsNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','synapse_props') 
    614          
    615         #I don't know how to deal with that 
    616         projectionNode.appendChild(synapse_propsNode) 
    617          
     657        connection_method = getattr(self,'_%s' % method) 
     658         
     659        projectionNode.appendChild(connection_method(methodParameters)) 
     660         
     661        PrettyPrint(xmldoc) 
     662         
     663     
     664     
     665    # --- Connection methods --------------------------------------------------- 
     666     
     667     
     668    def __connect(self,synapse_type,): 
     669        """ 
     670        Here this function doesn't have the same meaning than in neuron.py, it just creates the 
     671        neuroML template around the connectivity_pattern 
     672        """ 
     673        """ 
     674         <projection name="2"> 
     675            <source>CellGroupA</source> 
     676            <target>CellGroupB</target> 
     677            <synapse_props> 
     678                <synapse_type>DoubExpSynA</synapse_type> 
     679                <default_values/> 
     680            </synapse_props> 
     681            <connectivity_pattern> 
     682                <all_to_all/> 
     683            </connectivity_pattern> 
     684        </projection> 
     685        """ 
     686         
     687        synapse_propsNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','synapse_props') 
     688        projectionNode = self.domNode 
     689         
    618690        synapse_typeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','synapse_type') 
    619         #false values to make it valid 
    620         synapse_typeTextNode = xmldoc.createTextNode("DoubExpSynA") 
     691        synapse_typeTextNode = xmldoc.createTextNode(synapse_type) 
    621692        synapse_typeNode.appendChild(synapse_typeTextNode) 
    622693        synapse_propsNode.appendChild(synapse_typeNode) 
     
    624695        default_valuesNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','default_values') 
    625696        synapse_propsNode.appendChild(default_valuesNode) 
    626          
    627         """ 
    628         example of connectivity_pattern to add, must be generic 
    629              
    630             <connectivity_pattern> 
    631                 <fixed_probability probability="0.5"></fixed_probability> 
    632             </connectivity_pattern> 
    633          
    634          
    635         """ 
    636          
     697        projectionNode.appendChild(synapse_propsNode) 
     698     
     699     
     700    def _allToAll(self,parameters=None,synapse_type=None): 
     701        """ 
     702        Connect all cells in the presynaptic population to all cells in the 
     703        postsynaptic population. 
     704        """ 
     705        """ 
     706        <connectivity_pattern> 
     707            <all_to_all/> 
     708        </connectivity_pattern> 
     709        """ 
     710         
     711        #still have to create the connectivity_pattern node which will be created by its corresponding method 
     712        __connect(self,parameters,synapse_type) 
    637713        connectivity_patternNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connectivity_pattern') 
    638         projectionNode.appendChild(connectivity_patternNode) 
    639          
    640         methodNode = xmldoc.createElementNS('http://morphml.org/networkml/schema',method) 
    641         for key in methodParameters: 
    642             methodNode.setAttribute(key,methodParameters[key]) 
    643          
    644         connectivity_patternNode.appendChild(methodNode) 
    645          
    646          
    647         PrettyPrint(xmldoc) 
    648          
    649          
    650          
    651          
    652     # --- Connection methods --------------------------------------------------- 
    653      
    654     def _allToAll(self,parameters=None): 
    655         """ 
    656         Connect all cells in the presynaptic population to all cells in the postsynaptic population. 
    657         """ 
    658         allow_self_connections = True # when pre- and post- are the same population, 
    659                                       # is a cell allowed to connect to itself? 
    660         if parameters and parameters.has_key('allow_self_connections'): 
    661             allow_self_connections = parameters['allow_self_connections'] 
    662         raise "Method not yet implemented" 
    663         return len(presynaptic_neurons) * len(postsynaptic_neurons) 
    664      
    665     def _oneToOne(self): 
     714         
     715        connectivity_patternTypeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','all_to_all') 
     716        connectivity_patternNode.appendChild(connectivity_patternTypeNode) 
     717         
     718        return connectivity_patternNode 
     719     
     720         
     721    def _oneToOne(self,synapse_type=None): 
    666722        """ 
    667723        Where the pre- and postsynaptic populations have the same size, connect 
     
    673729        in row i of a 2D post population of size (n,m). 
    674730        """ 
    675         raise "Method not yet implemented" 
    676      
    677     def _fixedProbability(self,parameters): 
     731        __connect(self,parameters,synapse_type) 
     732        connectivity_patternNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connectivity_pattern') 
     733         
     734        connectivity_patternTypeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','one_to_one') 
     735        connectivity_patternNode.appendChild(connectivity_patternTypeNode) 
     736         
     737        return connectivity_patternNode 
     738 
     739     
     740    def _fixedProbability(self,parameters,synapse_type=None): 
    678741        """ 
    679742        For each pair of pre-post cells, the connection probability is constant. 
     
    686749            if parameters.has_key('allow_self_connections'): 
    687750                allow_self_connections = parameters['allow_self_connections'] 
    688           
    689         raise "Method not yet implemented" 
    690      
    691     def _distanceDependentProbability(self,parameters): 
     751 
     752        __connect(self,parameters,synapse_type) 
     753        connectivity_patternNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connectivity_pattern') 
     754         
     755        connectivity_patternTypeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','fixed_probability') 
     756        connectivity_patternTypeNode.setAttribute('probability',p_connect) 
     757        connectivity_patternNode.appendChild(connectivity_patternTypeNode) 
     758         
     759        return connectivity_patternNode 
     760 
     761 
     762    def _distanceDependentProbability(self,parameters,synapse_type=None): 
    692763        """ 
    693764        For each pair of pre-post cells, the connection probability depends on distance. 
     
    695766        for probability, involving 'd', e.g. "exp(-abs(d))", or "float(d<3)" 
    696767        """ 
    697         allow_self_connections = True 
    698         if type(parameters) == types.StringType: 
    699             d_expression = parameters 
    700         else: 
    701             d_expression = parameters['d_expression'] 
    702             if parameters.has_key('allow_self_connections'): 
    703                 allow_self_connections = parameters['allow_self_connections'] 
    704         raise "Method not yet implemented" 
    705      
    706     def _fixedNumberPre(self,parameters): 
     768        raise Exception("Method not yet implemented") 
     769         
     770 
     771    def _fixedNumberPre(self,parameters,synapse_type=None): 
    707772        """Each presynaptic cell makes a fixed number of connections.""" 
     773        """ 
     774        <connectivity_pattern> 
     775           <per_cell_connection num_per_source="1.2" max_per_target="2.3" direction="PreToPost"/> 
     776        </connectivity_pattern> 
     777        """ 
     778        self.synapse_type = synapse_type 
    708779        allow_self_connections = True 
    709780        if type(parameters) == types.IntType: 
    710781            n = parameters 
     782            assert n > 0 
     783            fixed = True 
    711784        elif type(parameters) == types.DictType: 
    712             if parameters.has_key['n']: # all cells have same number of connections 
    713                 n = parameters['n'] 
    714             elif parameters.has_key['rng']: # number of connections per cell follows a distribution 
    715                 rng = parameters['rng'] 
     785            if parameters.has_key('n'): # all cells have same number of connections 
     786                n = int(parameters['n']) 
     787                assert n > 0 
     788                fixed = True 
     789            elif parameters.has_key('rand_distr'): # number of connections per cell follows a distribution 
     790                rand_distr = parameters['rand_distr'] 
     791                assert isinstance(rand_distr,RandomDistribution) 
     792                fixed = False 
    716793            if parameters.has_key('allow_self_connections'): 
    717794                allow_self_connections = parameters['allow_self_connections'] 
    718         else : # assume parameters is a rng 
    719             rng = parameters 
    720         raise "Method not yet implemented" 
    721      
    722     def _fixedNumberPost(self,parameters): #CHEAT CHEAT CHEAT 
     795        elif isinstance(parameters, RandomDistribution): 
     796            rand_distr = parameters 
     797            fixed = False 
     798        else: 
     799            raise Exception("Invalid argument type: should be an integer, dictionary or RandomDistribution object.") 
     800                 
     801        __connect(self,parameters,synapse_type) 
     802        connectivity_patternNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connectivity_pattern') 
     803         
     804        connectivity_patternTypeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','per_cell_connection') 
     805        connectivity_patternTypeNode.setAttribute('num_per_source',n) 
     806        connectivity_patternTypeNode.setAttribute('max_per_target',n) 
     807        connectivity_patternTypeNode.setAttribute('direction','PreToPost') 
     808        connectivity_patternNode.appendChild(connectivity_patternTypeNode) 
     809         
     810        return connectivity_patternNode 
     811     
     812             
     813    def _fixedNumberPost(self,parameters,synapse_type=None): 
    723814        """Each postsynaptic cell receives a fixed number of connections.""" 
     815        """ 
     816        <connectivity_pattern> 
     817           <per_cell_connection num_per_source="1.2" max_per_target="2.3" direction="PostToPre"/> 
     818        </connectivity_pattern> 
     819        """ 
     820        self.synapse_type = synapse_type 
    724821        allow_self_connections = True 
    725822        if type(parameters) == types.IntType: 
    726823            n = parameters 
     824            assert n > 0 
     825            fixed = True 
    727826        elif type(parameters) == types.DictType: 
    728             if parameters.has_key['n']: # all cells have same number of connections 
    729                 n = parameters['n'] 
    730             elif parameters.has_key['rng']: # number of connections per cell follows a distribution 
    731                 rng = parameters['rng'] 
     827            if parameters.has_key('n'): # all cells have same number of connections 
     828                n = int(parameters['n']) 
     829                assert n > 0 
     830                fixed = True 
     831            elif parameters.has_key('rand_distr'): # number of connections per cell follows a distribution 
     832                rand_distr = parameters['rand_distr'] 
     833                assert isinstance(rand_distr,RandomDistribution) 
     834                fixed = False 
    732835            if parameters.has_key('allow_self_connections'): 
    733836                allow_self_connections = parameters['allow_self_connections'] 
    734         else : # assume parameters is a rng 
    735             rng = parameters 
    736          
    737         raise "Method not yet implemented" 
    738      
    739     def _fromFile(self,parameters): 
     837        elif isinstance(parameters, RandomDistribution): 
     838            rand_distr = parameters 
     839            fixed = False 
     840        else: 
     841            raise Exception("Invalid argument type: should be an integer, dictionary or RandomDistribution object.") 
     842                 
     843        __connect(self,parameters,synapse_type) 
     844        connectivity_patternNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connectivity_pattern') 
     845         
     846        connectivity_patternTypeNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','per_cell_connection') 
     847        connectivity_patternTypeNode.setAttribute('num_per_source',n) 
     848        connectivity_patternTypeNode.setAttribute('max_per_target',n) 
     849        connectivity_patternTypeNode.setAttribute('direction','PostToPre') 
     850        connectivity_patternNode.appendChild(connectivity_patternTypeNode) 
     851         
     852        return connectivity_patternNode 
     853 
     854 
     855 
     856   def _fromFile(self,parameters,synapse_type=None): 
    740857        """ 
    741858        Load connections from a file. 
    742859        """ 
     860        lines =[] 
    743861        if type(parameters) == types.FileType: 
    744862            fileobj = parameters 
    745             # check fileobj is already open for reading 
     863            # should check here that fileobj is already open for reading 
     864            lines = fileobj.readlines() 
    746865        elif type(parameters) == types.StringType: 
    747866            filename = parameters 
    748867            # now open the file... 
     868            f = open(filename,'r') 
     869            lines = f.readlines() 
    749870        elif type(parameters) == types.DictType: 
    750871            # dict could have 'filename' key or 'file' key 
    751872            # implement this... 
    752             pass 
    753         raise "Method not yet implemented" 
    754          
    755     def _fromList(self,parameters): 
    756         """ 
    757         Read connections from a list of lists, or somesuch... 
    758         """ 
    759         # Need to implement parameter parsing here... 
    760         raise "Method not yet implemented" 
     873            raise "Argument type not yet implemented" 
     874         
     875        # We read the file and gather all the data in a list of tuples (one per line) 
     876        input_tuples = [] 
     877        for line in lines: 
     878            single_line = line.rstrip() 
     879            single_line = single_line.split("\t", 4) 
     880            input_tuples.append(single_line)     
     881        f.close() 
     882         
     883        return self._fromList(input_tuples, synapse_type) 
     884     
     885    def _fromList(self,conn_list,synapse_type=None): 
     886        """ 
     887        Read connections from a list of tuples, 
     888        containing ['src[x,y]', 'tgt[x,y]', 'weight', 'delay'] 
     889        """ 
     890        """ 
     891        <projection name="NetworkConnection"> 
     892            <source>CellGroupA</source> 
     893            <target>CellGroupB</target> 
     894            <synapse_props> 
     895                <synapse_type>DoubExpSynA</synapse_type> 
     896                <default_values internal_delay="5" weight="1" threshold="-20"/> 
     897            </synapse_props> 
     898            <connections> 
     899                <connection id="1"> 
     900                    <pre cell_id="3" segment_id = "0"/> 
     901                    <post cell_id="1" segment_id = "1"/> 
     902                    <properties internal_delay="10" weight="0.5"/>                    <!-- adjusted value --> 
     903                </connection> 
     904            </connections> 
     905        </projection> 
     906        """ 
     907        __connect(self,synapse_type) 
     908        projectionNode = self.domNode 
     909        connectionsNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connections') 
     910        projectionNode.appendChild(connectionsNode) 
     911         
     912        # Then we go through those tuple and extract the fields 
     913        for i in xrange(len(conn_list)): 
     914            src    = conn_list[i][0] 
     915            tgt    = conn_list[i][1] 
     916            weight = eval(conn_list[i][2]) 
     917            delay  = eval(conn_list[i][3]) 
     918            src = "[%s" %src.split("[",1)[1] 
     919            tgt = "[%s" %tgt.split("[",1)[1] 
     920            src  = eval("self.pre%s" % src) 
     921            tgt  = eval("self.post%s" % tgt) 
     922             
     923            connectionNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','connection') 
     924            connectionNode.setAttribute('id',i) 
     925            preNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','pre') 
     926            preNode.setAttribute('cell_id',src) 
     927            connectionNode.appendChild(preNode) 
     928             
     929            postNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','post') 
     930            postNode.setAttribute('cell_id',tgt) 
     931            connectionNode.appendChild(postNode) 
     932             
     933            propertiesNode = xmldoc.createElementNS('http://morphml.org/networkml/schema','properties') 
     934            propertiesNode.setAttribute('internal_delay',delay) 
     935            propertiesNode.setAttribute('weight',weight) 
     936            connectionNode.appendChild(propertiesNode) 
     937            connectionsNode.appendChild(connectionNode) 
     938             
     939         
     940        return connectivity_patternNode 
     941         
    761942     
    762943    # --- Methods for setting connection parameters ---------------------------- 
     
    765946        """ 
    766947        w can be a single number, in which case all weights are set to this 
    767         value, or an array with the same dimensions as the Projection array. 
    768         """ 
    769         if type(w) == types.FloatType or type(w) == types.IntType: 
    770             w = w*1000 
    771         for src,tgt in zip(self._sources,self._targets): 
    772             # set weight 
    773             raise "Method not yet implemented" 
    774         else: 
    775             raise "Method needs changing to reflect the new API" # (w can be an array) 
    776      
    777     def randomizeWeights(self,rng): 
    778         """ 
    779         Set weights to random values taken from rng. 
    780         """ 
    781         # Arguably, we could merge this with set_weights just by detecting the 
    782         # argument type. It could make for easier-to-read simulation code to 
    783         # give it a separate name, though. Comments? 
    784         raise "Method not yet implemented" 
     948        value, or a list/1D array of length equal to the number of connections 
     949        in the population. 
     950        Weights should be in nA for current-based and µS for conductance-based 
     951        synapses. 
     952        """ 
     953        raise Exception("Method not yet implemented") 
     954 
     955 
     956    def randomizeWeights(self,rand_distr): 
     957        """ 
     958        Set weights to random values taken from rand_distr. 
     959        """ 
     960        # If we have a native rng, we do the loops in hoc. Otherwise, we do the loops in 
     961        # Python 
     962        raise Exception("Method not yet implemented") 
     963         
     964         
    785965     
    786966    def setDelays(self,d): 
     
    789969        value, or an array with the same dimensions as the Projection array. 
    790970        """ 
    791         if type(d) == types.FloatType or type(d) == types.IntType: 
    792             for src,tgt in zip(self._sources,self._targets): 
    793                 # set delays 
    794                 raise "Method not yet implemented" 
    795         else: 
    796             raise "Method needs changing to reflect the new API" # (d can be an array) 
    797      
    798     def randomizeDelays(self,rng): 
    799         """ 
    800         Set delays to random values taken from rng. 
    801         """ 
    802         raise "Method not yet implemented" 
    803      
     971        raise Exception("Method not yet implemented") 
     972 
     973         
     974    def randomizeDelays(self,rand_distr): 
     975        """ 
     976        Set delays to random values taken from rand_distr. 
     977        """    
     978        # If we have a native rng, we do the loops in hoc. Otherwise, we do the loops in 
     979        # Python   
     980        raise Exception("Method not yet implemented") 
     981 
     982         
     983    def setTopographicDelays(self,delay_rule,rand_distr=None): 
     984        """ 
     985        Set delays according to a connection rule expressed in delay_rule, based 
     986        on the delay distance 'd' and an (optional) rng 'rng'. For example, 
     987        the rule can be "rng*d + 0.5", with "a" extracted from the rng and 
     988        d being the distance. 
     989        """ 
     990        raise Exception("Method not yet implemented") 
     991         
    804992    def setThreshold(self,threshold): 
    805993        """ 
     
    807995        threshold crossing, set the value of this threshold. 
    808996        """ 
    809         raise "Method not yet implemented" 
    810      
     997        # This is a bit tricky, because in NEST the spike threshold is a 
     998        # property of the cell model, whereas in NEURON it is a property of the 
     999        # connection (NetCon). 
     1000        raise Exception("Method not yet implemented") 
    8111001     
    8121002    # --- Methods relating to synaptic plasticity ------------------------------ 
     
    8141004    def setupSTDP(self,stdp_model,parameterDict): 
    8151005        """Set-up STDP.""" 
    816         raise "Method not yet implemented" 
     1006         
     1007        # Define the objref to handle plasticity 
     1008        raise Exception("Method not yet implemented") 
    8171009     
    8181010    def toggleSTDP(self,onoff): 
    819         """Turn plasticity on or off.""" 
    820         raise "Method not yet implemented" 
     1011        """Turn plasticity on or off.  
     1012        onoff = True => ON  and onoff = False => OFF. By defaut, it is on.""" 
     1013        # We do the loop in hoc, to speed up the code 
     1014        raise Exception("Method not yet implemented") 
     1015         
    8211016     
    8221017    def setMaxWeight(self,wmax): 
    8231018        """Note that not all STDP models have maximum or minimum weights.""" 
    824         raise "Method not yet implemented" 
     1019        # We do the loop in hoc, to speed up the code 
     1020        raise Exception("Method not yet implemented") 
     1021 
    8251022     
    8261023    def setMinWeight(self,wmin): 
    8271024        """Note that not all STDP models have maximum or minimum weights.""" 
    828         raise "Method not yet implemented" 
     1025        # We do the loop in hoc, to speed up the code 
     1026        raise Exception("Method not yet implemented") 
     1027     
    8291028     
    8301029    # --- Methods for writing/reading information to/from file. ---------------- 
    8311030     
    832     def saveConnections(self,filename): 
     1031    def saveConnections(self,filename,gather=False): 
    8331032        """Save connections to file in a format suitable for reading in with the 
    8341033        'fromFile' method.""" 
    835         raise "Method not yet implemented" 
    836      
    837     def printWeights(self,filename,format=None): 
     1034        raise Exception("Method not yet implemented") 
     1035     
     1036    def printWeights(self,filename,format=None,gather=True): 
    8381037        """Print synaptic weights to file.""" 
    839         raise "Method not yet implemented" 
    840      
     1038        raise Exception("Method not yet implemented") 
     1039 
     1040 
    8411041    def weightHistogram(self,min=None,max=None,nbins=10): 
    8421042        """ 
     
    8471047        # it is arguable whether functions operating on the set of weights 
    8481048        # should be put here or in an external module. 
    849         raise "Method not yet implemented" 
     1049        raise Exception("Method not yet implemented") 
     1050 
    8501051  
    8511052# ============================================================================== 
     
    8571058 
    8581059# ============================================================================== 
    859  
    860 class Random: 
    861     """Wrapper class for random number generators. The idea is to be able to use 
    862     either simulator-native rngs, which may be more efficient, or a standard 
    863     python rng, e.g. numpy.Random, which would allow the same random numbers to 
    864     be used across different simulators, or simply to read externally-generated 
    865     numbers from files.""" 
    866      
    867     nRand = 0 
    868      
    869     def __init__(self,type='default',distribution='uniform',label=None,seed=123456789): 
    870         """ """ 
    871         raise "Not yet implemented." 
    872          
    873     def next(self,n): 
    874         """Return n random numbers from the distribution.""" 
    875         raise "Not yet implemented." 
  • branches/connector-class/nest.py

    r81 r88  
    476476        return id 
    477477     
    478  
    479      
    480478    def __len__(self): 
    481479        """Returns the total number of cells in the population.""" 
    482480        return self.size 
     481     
     482    def __iter__(self): 
     483        return self.cell.flat 
     484 
     485    def __address_gen(self): 
     486        """ 
     487        Generator to produce an iterator over all cells on this node, 
     488        returning addresses. 
     489        """ 
     490        for i in self.__iter__(): 
     491            yield self.locate(i) 
     492         
     493    def addresses(self): 
     494        return self.__address_gen() 
     495     
     496    def ids(self): 
     497        return self.__iter__() 
    483498     
    484499    def locate(self, id): 
  • branches/connector-class/neuron.py

    r83 r88  
    761761        return self.fullgidlist[index] 
    762762 
     763    def __iter__(self): 
     764        return self.__gid_gen() 
     765 
     766    def __address_gen(self): 
     767        """ 
     768        Generator to produce an iterator over all cells on this node, 
     769        returning addresses. 
     770        """ 
     771        for i in self.gidlist: 
     772            yield self.locate(i) 
     773     
     774    def __gid_gen(self): 
     775        """ 
     776        Generator to produce an iterator over all cells on this node, 
     777        returning gids. 
     778        """ 
     779        for i in self.gidlist: 
     780            yield i 
     781         
     782    def addresses(self): 
     783        return self.__address_gen() 
     784     
     785    def ids(self): 
     786        return self.__gid_gen() 
    763787         
    764788    def locate(self,id): 
     
    11321156                        '%s = new List()' % self.hoc_label] 
    11331157        connection_method = getattr(self,'_%s' % method) 
     1158        self.synapse_type = target 
     1159        self._syn_objref = _translate_synapse_type(self.synapse_type) 
    11341160         
    11351161        if target: 
     
    11741200    # --- Connection methods --------------------------------------------------- 
    11751201     
    1176     def __connect(self,src,tgt,synapse_type): 
     1202    def __connect(self,src,tgt): 
    11771203        """ 
    11781204        Write hoc commands to connect a single pair of neurons. 
    11791205        """ 
    1180         syn_objref = _translate_synapse_type(synapse_type) 
    11811206        cmdlist = ['nc = pc.gid_connect(%d,%s.object(%d).%s)' % (src, 
    11821207                                                                 self.post.hoc_label, 
    11831208                                                                 self.post.gidlist.index(tgt), 
    1184                                                                  syn_objref), 
     1209                                                                 self._syn_objref), 
    11851210                'tmp = %s.append(nc)' % self.hoc_label] 
    11861211        self.connections.append((src,tgt)) 
    11871212        return cmdlist 
    11881213     
    1189     def _allToAll(self,parameters=None,synapse_type=None): 
     1214    def _allToAll(self,parameters=None): 
    11901215        """ 
    11911216        Connect all cells in the presynaptic population to all cells in the 
     
    12001225            for src in self.pre.fullgidlist: 
    12011226                if allow_self_connections or self.pre != self.post or tgt != src: 
    1202                     hoc_commands += self.__connect(src,tgt,synapse_type) 
     1227                    hoc_commands += self.__connect(src,tgt) 
    12031228        return hoc_commands 
    12041229         
    1205     def _oneToOne(self,synapse_type=None): 
     1230    def _oneToOne(self,parameters=None): 
    12061231        """ 
    12071232        Where the pre- and postsynaptic populations have the same size, connect 
     
    12171242            for tgt in self.post.gidlist: 
    12181243                src = tgt - self.post.gid_start + self.pre.gid_start 
    1219                 hoc_commands += self.__connect(src,tgt,synapse_type) 
     1244                hoc_commands += self.__connect(src,tgt) 
    12201245        else: 
    12211246            raise Exception("Method '%s' not yet implemented for the case where presynaptic and postsynaptic Populations have different sizes." % sys._getframe().f_code.co_name) 
    12221247        return hoc_commands 
    12231248     
    1224     def _fixedProbability(self,parameters,synapse_type=None): 
     1249    def _fixedProbability(self,parameters): 
    12251250        """ 
    12261251        For each pair of pre-post cells, the connection probability is constant. 
     
    12471272                    if HocToPy.get('rng.repick()','float') < p_connect: 
    12481273                        if allow_self_connections or self.pre != self.post or tgt != src: 
    1249                             self.__connect(src,tgt,synapse_type) 
     1274                            self.__connect(src,tgt) 
    12501275            return hoc_commands 
    12511276        else: # use Python RNG 
     
    12561281                    if rarr[j] < p_connect: 
    12571282                        if allow_self_connections or self.pre != self.post or tgt != src: 
    1258                             hoc_commands += self.__connect(src,tgt,synapse_type) 
     1283                            hoc_commands += self.__connect(src,tgt) 
    12591284        return hoc_commands 
    12601285 
    1261     def _distanceDependentProbability(self,parameters,synapse_type=None): 
     1286    def _distanceDependentProbability(self,parameters): 
    12621287        """ 
    12631288        For each pair of pre-post cells, the connection probability depends on distance. 
     
    13171342                        if alphanum: 
    13181343                            if rarr[j] < eval(distance_expression): 
    1319                                 hoc_commands += self.__connect(src,tgt,synapse_type) 
     1344                                hoc_commands += self.__connect(src,tgt) 
    13201345                        elif eval(distance_expression): 
    1321                             hoc_commands += self.__connect(src,tgt,synapse_type) 
     1346                            hoc_commands += self.__connect(src,tgt) 
    13221347        return hoc_commands 
    13231348     
    1324     def _fixedNumberPre(self,parameters,synapse_type=None): 
     1349    def _fixedNumberPre(self,parameters): 
    13251350        """Each presynaptic cell makes a fixed number of connections.""" 
    1326         self.synapse_type = synapse_type 
    13271351        allow_self_connections = True 
    13281352        if type(parameters) == types.IntType: 
     
    13581382            for tgt in rng.permutation(self.post.gidlist)[0:n]: 
    13591383                if allow_self_connections or (src != tgt): 
    1360                     hoc_commands += self.__connect(src,tgt,synapse_type) 
     1384                    hoc_commands += self.__connect(src,tgt) 
    13611385        return hoc_commands 
    13621386             
    1363     def _fixedNumberPost(self,parameters,synapse_type=None): 
     1387    def _fixedNumberPost(self,parameters): 
    13641388        """Each postsynaptic cell receives a fixed number of connections.""" 
    1365         self.synapse_type = synapse_type 
    13661389        allow_self_connections = True 
    13671390        if type(parameters) == types.IntType: 
     
    13971420            for src in rng.permutation(self.pre.gidlist)[0:n]: 
    13981421                if allow_self_connections or (src != tgt): 
    1399                     hoc_commands += self.__connect(src,tgt,synapse_type) 
     1422                    hoc_commands += self.__connect(src,tgt) 
    14001423        return hoc_commands 
    14011424     
    1402     def _fromFile(self,parameters,synapse_type=None): 
     1425    def _fromFile(self,parameters): 
    14031426        """ 
    14041427        Load connections from a file. 
     
    14281451            input_tuples.append((eval(src),eval(tgt),float(w),float(d))) 
    14291452        f.close() 
    1430         return self._fromList(input_tuples, synapse_type) 
    1431      
    1432     def _fromList(self,conn_list,synapse_type=None): 
     1453        return self._fromList(input_tuples) 
     1454     
     1455    def _fromList(self,conn_list): 
    14331456        """ 
    14341457        Read connections from a list of tuples, 
     
    14401463         
    14411464        # Then we go through those tuple and extract the fields 
    1442         self.synapse_type = synapse_type 
    14431465        for i in xrange(len(conn_list)): 
    14441466            src, tgt, weight, delay = conn_list[i][:] 
    14451467            src = self.pre[tuple(src)] 
    14461468            tgt = self.post[tuple(tgt)] 
    1447             hoc_commands += self.__connect(src,tgt,synapse_type) 
     1469            hoc_commands += self.__connect(src,tgt) 
    14481470            hoc_commands += ['%s.object(%d).weight = %f' % (self.hoc_label, i, float(weight)),  
    14491471                             '%s.object(%d).delay = %f'  % (self.hoc_label, i, float(delay))] 
  • branches/connector-class/pcsim.py

    r75 r88  
    749749        assert orig_addr == self.locate(id), 'index=%s addr=%s id=%s locate(id)=%s' % (index, orig_addr, id, self.locate(id)) 
    750750        return id 
    751          
     751     
     752    def __iter__(self): 
     753        return self.__gid_gen() 
     754 
     755    def __address_gen(self): 
     756        """ 
     757        Generator to produce an iterator over all cells on this node, 
     758        returning addresses. 
     759        """ 
     760        for i in self.__iter__(): 
     761            yield self.locate(i) 
     762     
     763    def __gid_gen(self): 
     764        """ 
     765        Generator to produce an iterator over all cells on this node, 
     766        returning gids. 
     767        """ 
     768        ids = self.pcsim_population.idVector() 
     769        for i in ids: 
     770            yield ID(i-ids[0]) 
     771             
     772    def addresses(self): 
     773        return self.__address_gen() 
     774     
     775    def ids(self): 
     776        return self.__iter__() 
    752777         
    753778    def locate(self, id): 
  • branches/connector-class/test/nesttests.py

    r62 r88  
    218218    def testInvalidIndexDimension(self): 
    219219        self.assertRaises(common.InvalidDimensionsError, self.net1.__getitem__, (10,2)) 
     220 
     221# ============================================================================== 
     222class PopulationIteratorTest(unittest.TestCase): 
     223    """Tests of the Population class iterators.""" 
     224     
     225    def setUp(self): 
     226        nest.setup() 
     227        nest.Population.nPop = 0 
     228        self.net1 = nest.Population((10,),nest.IF_curr_alpha) 
     229        self.net2 = nest.Population((2,4,3),nest.IF_curr_exp) 
     230        self.net3 = nest.Population((2,2,1),nest.SpikeSourceArray) 
     231        self.net4 = nest.Population((1,2,1),nest.SpikeSourceArray) 
     232        self.net5 = nest.Population((3,3),nest.IF_cond_alpha) 
     233         
     234    def testIter(self): 
     235        """This needs more thought for the distributed case.""" 
     236        for net in self.net1, self.net2: 
     237            ids = [i for i in net] 
     238            self.assertEqual(ids, net.cell.flatten().tolist()) 
     239            self.assert_(isinstance(ids[0], nest.ID)) 
     240             
     241    def testAddressIter(self): 
     242        for net in self.net1, self.net2: 
     243            for id,addr in zip(net.ids(),net.addresses()): 
     244                self.assertEqual(id, net[addr]) 
     245                self.assertEqual(addr, net.locate(id)) 
    220246 
    221247# ============================================================================== 
  • branches/connector-class/test/neurontests.py

    r62 r88  
    238238    def testInvalidIndexDimension(self): 
    239239        self.assertRaises(common.InvalidDimensionsError, self.net1.__getitem__, (10,2)) 
    240          
     240      
     241# ============================================================================== 
     242class PopulationIteratorTest(unittest.TestCase): 
     243    """Tests of the Population class iterators.""" 
     244     
     245    def setUp(self): 
     246        neuron.Population.nPop = 0 
     247        self.net1 = neuron.Population((10,),neuron.IF_curr_alpha) 
     248        self.net2 = neuron.Population((2,4,3),neuron.IF_curr_exp) 
     249        self.net3 = neuron.Population((2,2,1),neuron.SpikeSourceArray) 
     250        self.net4 = neuron.Population((1,2,1),neuron.SpikeSourceArray) 
     251        self.net5 = neuron.Population((3,3),neuron.IF_cond_alpha) 
     252         
     253    def testIter(self): 
     254        """This needs more thought for the distributed case.""" 
     255        for net in self.net1, self.net2: 
     256            ids = [i for i in net] 
     257            self.assertEqual(ids, net.gidlist) 
     258            self.assert_(isinstance(ids[0], neuron.ID)) 
     259             
     260    def testAddressIter(self): 
     261        for net in self.net1, self.net2: 
     262            for id,addr in zip(net.ids(),net.addresses()): 
     263                self.assertEqual(id, net[addr]) 
     264                self.assertEqual(addr, net.locate(id)) 
     265             
     266     
    241267# ============================================================================== 
    242268class PopulationSetTest(unittest.TestCase): 
  • branches/connector-class/test/pcsimtests_population.py

    r74 r88  
    9393        self.assertRaises(common.InvalidDimensionsError, self.net1.__getitem__, (10,2)) 
    9494 
     95# ============================================================================== 
     96class PopulationIteratorTest(unittest.TestCase): 
     97    """Tests of the Population class iterators.""" 
     98     
     99    def setUp(self): 
     100        setup() 
     101        Population.nPop = 0 
     102        self.net1 = Population((10,),IF_curr_alpha) 
     103        self.net2 = Population((2,4,3),IF_curr_exp) 
     104        self.net3 = Population((2,2,1),SpikeSourceArray) 
     105        self.net4 = Population((1,2,1),SpikeSourceArray) 
     106        self.net5 = Population((3,3),IF_curr_exp) 
     107         
     108    def testIter(self): 
     109        """This needs more thought for the distributed case.""" 
     110        for net in self.net1, self.net2: 
     111            ids = [i for i in net] 
     112            idVec = numpy.array(net.pcsim_population.idVector()) 
     113            idVec -= idVec[0] 
     114            self.assertEqual(ids, idVec.tolist()) 
     115            self.assert_(isinstance(ids[0], ID)) 
     116             
     117    def testAddressIter(self): 
     118        for net in self.net1, self.net2: 
     119            for id,addr in zip(net.ids(),net.addresses()): 
     120                self.assertEqual(id, net[addr]) 
     121                self.assertEqual(addr, net.locate(id)) 
     122                 
    95123 # ============================================================================== 
    96124class PopulationSetTest(unittest.TestCase):