Changeset 88

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

Merged changes r84:87 from trunk

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • 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 fo