Changeset 414

Show
Ignore:
Timestamp:
07/16/08 09:47:16 (1 month ago)
Author:
apdavison
Message:

Harmonization of describe() methods across simulators, by moving its definition into common.

describe() now returns a string, rather than printing directly to stdout. This lets it be used for writing to log files, etc. You will now have to use print p.describe() to obtain the old behaviour.

describe() now also takes a template argument, allowing the output to be customized.

Work still to be done in extending to the information that is produced by describe(), and in cascading different classes (e.g. Projection.describe() could call Connector.describe()...)

Files:

Legend:

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

    r342 r414  
    532532            f.close() 
    533533        pass 
    534       
    535     def describe(self): 
    536         """ 
    537         Returns a human readable description of the population 
    538         """ 
    539         pass 
    540          
    541           
    542534 
    543535     
     
    750742        # should be put here or in an external module. 
    751743        raise Exception("Method not yet implemented") 
    752      
    753     def describe(self): 
    754         """ 
    755         Return a human readable description of the projection 
    756         """ 
    757         pass 
     744 
    758745 
    759746# ============================================================================== 
  • trunk/src/common.py

    r413 r414  
    1111from math import * 
    1212from pyNN import random 
     13from string import Template 
    1314 
    1415DEFAULT_WEIGHT = 0.0 
     
    367368        return [name for name in cls.translations if name not in cls.simple_parameters()+cls.scaled_parameters()] 
    368369         
    369  
    370370    def update_parameters(self, parameters): 
    371371        """ 
     
    374374        self.parameters.update(self.translate(parameters)) 
    375375         
     376    def describe(self, template='standard'): 
     377        return str(self) 
     378     
    376379 
    377380class StandardCellType(StandardModelType): 
     
    935938        return _abstract_method(self) 
    936939     
    937     def describe(self): 
     940    def describe(self, template='standard'): 
    938941        """ 
    939942        Returns a human readable description of the population 
    940943        """ 
    941         return _abstract_method(self) 
     944        if template == 'standard': 
     945            #lines = ['==== Population $label ====', 
     946            #         '  Dimensions: $dim', 
     947            #         '  Local cells: $n_cells_local', 
     948            #         '  Cell type: $celltype', 
     949            #         '  ID range: $first_id-$last_id', 
     950            #         '  First cell on this node:', 
     951            #         '    ID: $local_first_id', 
     952            #         '    Parameters: $cell_parameters'] 
     953            lines = ['------- Population description -------', 
     954                     'Population called $label is made of $n_cells cells [$n_cells_local being local]'] 
     955            if self.parent: 
     956                lines += ['This population is a subpopulation of population $parent_label'] 
     957            lines += ["-> Cells are aranged on a ${ndim}D grid of size $dim", 
     958                      "-> Celltype is $celltype", 
     959                      "-> ID range is $first_id-$last_id", 
     960                      "-> Cell Parameters used for cell[0] are: "] 
     961            for name, value in self.index(0).get_parameters().items(): 
     962                lines += ["    | %-12s: %s" % (name, value)] 
     963            lines += ["--- End of Population description ----"] 
     964            template = "\n".join(lines) 
     965             
     966        context = self.__dict__.copy() 
     967        first_id = self._local_ids[0] 
     968        context.update(local_first_id=first_id) 
     969        context.update(cell_parameters=first_id.get_parameters()) 
     970        context.update(celltype=self.celltype.__class__.__name__) 
     971        context.update(n_cells=len(self)) 
     972        context.update(n_cells_local=len(self._local_ids)) 
     973        for k in context.keys(): 
     974            if k[0] == '_': 
     975                context.pop(k) 
     976                 
     977        if template == None: 
     978            return context 
     979        else: 
     980            return Template(template).substitute(context) 
    942981     
    943982    def getSubPopulation(self, cells): 
     
    9991038        self.label  = label 
    10001039        self.rng    = rng 
     1040        self._method = method 
    10011041        self.synapse_dynamics = synapse_dynamics 
    10021042        self.connection = None # access individual connections. To be defined by child, simulator-specific classes 
     
    12241264        return _abstract_method(self) 
    12251265     
    1226     def describe(self): 
     1266    def describe(self, template='standard'): 
    12271267        """ 
    12281268        Returns a human readable description of the projection 
    12291269        """ 
    1230         return _abstract_method(self) 
     1270        if template == 'standard': 
     1271            lines = ["------- Projection description -------", 
     1272                     "Projection $label from $pre_label [$pre_n_cells cells] to $post_label [$post_n_cells cells]", 
     1273                     "    | Connector : $_method", 
     1274                     "    | Weights : $weights", 
     1275                     "    | Delays : $delays", 
     1276                     "    | Plasticity : $plasticity", 
     1277                     "    | Num. connections : $nconn", 
     1278                    ]         
     1279            lines += ["---- End of Projection description -----"] 
     1280            template = '\n'.join(lines) 
     1281         
     1282        context = self.__dict__.copy() 
     1283        context.update({ 
     1284            'nconn': len(self), 
     1285            'pre_label': self.pre.label, 
     1286            'post_label': self.post.label, 
     1287            'pre_n_cells': self.pre.size, 
     1288            'post_n_cells': self.post.size, 
     1289            'weights': str(self._method.weights), 
     1290            'delays': str(self._method.delays), 
     1291        }) 
     1292        if self.synapse_dynamics: 
     1293            context.update(plasticity=self.synapse_dynamics.describe()) 
     1294        else: 
     1295            context.update(plasticity='None') 
     1296             
     1297        if template == None: 
     1298            return context 
     1299        else: 
     1300            return Template(template).substitute(context) 
    12311301 
    12321302 
     
    12781348        else: 
    12791349            raise Exception("delays is of type %s" % type(self.delays)) 
    1280        if self.check_connections: 
    1281            assert numpy.all(delays >= get_min_delay()), \ 
    1282            "Delay values must be greater than or equal to the minimum delay %g. The smallest delay is %g." % (get_min_delay(), delays.min()) 
    1283            assert numpy.all(delays <= get_max_delay()), \ 
    1284            "Delay values must be less than or equal to the maximum delay %s. The largest delay is %s" % (get_max_delay(), delays.max())                                                                                               
     1350        if self.check_connections: 
     1351            assert numpy.all(delays >= get_min_delay()), \ 
     1352            "Delay values must be greater than or equal to the minimum delay %g. The smallest delay is %g." % (get_min_delay(), delays.min()) 
     1353            assert numpy.all(delays <= get_max_delay()), \ 
     1354            "Delay values must be less than or equal to the maximum delay %s. The largest delay is %s" % (get_max_delay(), delays.max())                                                                                               
    12851355        self.d_index += N 
    12861356        return delays 
     
    14471517        self.fast = fast 
    14481518        self.slow = slow 
    1449                  
    1450                  
     1519     
     1520    def describe(self, template='standard'): 
     1521        if template == 'standard': 
     1522            lines = ["Short-term plasticity mechanism: $slow", 
     1523                     "Long-term plasticity mechanism: $fast"] 
     1524            template = "\n".join(lines) 
     1525        context = {'fast': self.fast.describe(), 
     1526                   'slow': self.slow.describe()} 
     1527        if template == None: 
     1528            return context 
     1529        else: 
     1530            return Template(template).substitute(context) 
     1531         
     1532         
    14511533class ShortTermPlasticityMechanism(StandardModelType): 
    14521534    """Abstract base class for models of short-term synaptic dynamics.""" 
  • trunk/src/nest1/__init__.py

    r408 r414  
    817817        os.system("rm %s" %tmpfile) 
    818818        result.close() 
    819       
    820     def describe(self): 
    821         """ 
    822         Returns a human readable description of the population 
    823         """ 
    824         print "\n------- Population description -------" 
    825         print "Population called %s is made of %d cells" %(self.label, len(self.cell.flatten())) 
    826         print "-> Cells are aranged on a %dD grid of size %s" %(len(self.dim), self.dim) 
    827         print "-> Celltype is %s" %self.celltype 
    828         print "-> Cell Parameters used for cell[0] (during initialization and now) are: "  
    829         for key, value in self.cellparams.items(): 
    830           print "\t|", key, "\t: ", "init->", value, "\t now->", pynest.getDict([self.cell.flatten()[0]])[0][key] 
    831         print "--- End of Population description ----" 
    832          
    833           
     819               
    834820 
    835821     
     
    12561242        # should be put here or in an external module. 
    12571243        raise Exception("Method not yet implemented") 
    1258      
    1259     def describe(self): 
    1260         """ 
    1261         Return a human readable description of the projection 
    1262         """ 
    1263         print "\n------- Projection description -------" 
    1264         print "Projection %s from %s [%d cells] to %s [%d cells]" %(self.label, self.pre.label, len(self.pre.cell),self.post.label, len(self.post.cell)) 
    1265         print "\t| Connector : " %self._method 
    1266         if isinstance(self._method.weights,RandomDistribution): 
    1267           print "\t| Weights : drawn from %s distribution with params %s "%(self._method.weights.name, self._method.weights.parameters) 
    1268         else: 
    1269           print "\t| Weights : ", self._method.weights 
    1270         if isinstance(self._method.delays,RandomDistribution): 
    1271           print "\t| Delays : drawn from %s distribution with params %s " %(self._method.delays.name, self._method.delays.parameters) 
    1272         else: 
    1273           print "\t| Delays : ", self._method.delays 
    1274         print "\t| Plasticity : ", self._plasticity_model 
    1275         print "\t --> %d connections have been created for this projection" %len(self) 
    1276         print "\tParameters of connection from %d to %d" %(self._sources[0], self._targets[0]) 
    1277         print "\t| weights : ", pynest.getWeight([self._sources[0]],self._targetPorts[0]) 
    1278         print "\t| delays : ", pynest.getDelay([self._sources[0]], self._targetPorts[0]) 
    1279          
    1280         print "---- End of Projection description -----" 
     1244 
    12811245 
    12821246# ============================================================================== 
  • trunk/src/nest2/__init__.py

    r413 r414  
    585585            self.cell = numpy.array([ ID(GID) for GID in self.cell ], ID) 
    586586            self.cell_local = self.cell[numpy.array(nest.GetStatus(self.cell.tolist(),'local'))] 
    587             self.first_id = self.cell.reshape(self.size,)[0] 
     587            self.first_id = self.cell.flatten()[0] 
     588            self.last_id = self.cell.flatten()[-1] 
    588589            for id in self.cell: 
    589590                id.parent = self 
     
    593594            if self.cellparams: 
    594595                nest.SetStatus(self.cell_local, [self.cellparams]) 
     596            self._local_ids = self.cell_local 
    595597 
    596598        if not self.label: 
     
    951953        return pop 
    952954 
    953     def describe(self): 
    954         """ 
    955         Return a human readable description of the population 
    956         """ 
    957         print "\n------- Population description -------" 
    958         print "Population called %s is made of %d cells [%d being local]" %(self.label, len(self.cell.flatten()), len(self.cell_local)) 
    959         if self.parent: 
    960             print "This population is a subpopulation of population %s" %self.parent.label 
    961         print "-> Cells are aranged on a %dD grid of size %s" %(len(self.dim), self.dim) 
    962         print "-> Celltype is %s" %self.celltype 
    963         print "-> Cell Parameters used for cell[0] (during initialization and now) are: " 
    964         for key, value in self.cellparams.items(): 
    965           print "\t|", key, "\t: ", "init->", value, "\t now->", nest.GetStatus([self.cell.flatten()[0]])[0][key] 
    966         print "--- End of Population description ----" 
    967  
    968955 
    969956class Projection(common.Projection): 
     
    10241011        self._sources = []     # holds gids 
    10251012        self.synapse_type = target 
    1026         self._method = method 
    10271013 
    10281014        if synapse_dynamics and synapse_dynamics.fast and synapse_dynamics.slow: 
     
    13681354        f.close() 
    13691355 
    1370  
    13711356    def weightHistogram(self, min=None, max=None, nbins=10): 
    13721357        """ 
     
    13801365        return numpy.histogram(self.getWeights(format='list', gather=True), bins) # returns n, bins 
    13811366 
    1382     def describe(self): 
    1383         """ 
    1384         Return a human readable description of the projection 
    1385         """ 
    1386         print "\n------- Projection description -------" 
    1387         print "Projection %s from %s [%d cells] to %s [%d cells]" %(self.label, self.pre.label, len(self.pre.cell),self.post.label, len(self.post.cell)) 
    1388         print "\t| Connector : %s" %self._method 
    1389         if isinstance(self._method.weights,RandomDistribution): 
    1390           print "\t| Weights : drawn from %s distribution with params %s "%(self._method.weights.name, self._method.weights.parameters) 
    1391         else: 
    1392           print "\t| Weights : ", self._method.weights 
    1393         if isinstance(self._method.delays,RandomDistribution): 
    1394           print "\t| Delays : drawn from %s distribution with params %s " %(self._method.delays.name, self._method.delays.parameters) 
    1395         else: 
    1396           print "\t| Delays: ", self._method.delays 
    1397         print "\t| Plasticity : ", self._plasticity_model 
    1398         print "\t ----> %d connections have been created for this projection" %len(self) 
    1399         print "\tParameters of connection from %d to %d [port %d]" %(self._sources[0], self._targets[0], self._target_ports[0]) 
     1367    def describe(self, template='standard'): 
     1368        """ 
     1369        Returns a human readable description of the projection 
     1370        """ 
     1371        description = common.Projection.describe(self, template) 
     1372        description += "\n    Parameters of connection from %d to %d [port %d]" % (self._sources[0], self._targets[0], self._target_ports[0]) 
    14001373        dict = nest.GetConnections([self.pre.cell.flat[0]], self._plasticity_model)[0] 
    14011374        for i in xrange(len(self._targets)): 
     
    14031376            if len(idx) > 0:  
    14041377                for key, value in dict.items(): 
    1405                     print "\t| ", key, ": ", value[idx[0]] 
     1378                    description += "\n    | %s: %s" % (key, value[idx[0]]) 
    14061379                break 
    1407  
    1408         print "---- End of Projection description -----" 
     1380        description += "\n---- End of NEST-specific Projection description -----" 
     1381        return description 
    14091382 
    14101383# ============================================================================== 
  • trunk/src/neuron/__init__.py

    r391 r414  
    728728        self.gidlist     = [self.fullgidlist[i+myid] for i in range(0, len(self.fullgidlist), nhost) if i < len(self.fullgidlist)-myid] 
    729729        self.first_id   = gid 
     730         
    730731 
    731732        # Write hoc commands 
     
    743744        Population.nPop += 1 
    744745        gid = gid+self.size 
     746        self.last_id =  gid-1 
    745747 
    746748        # We add the gidlist of the population to the global gidlist 
     
    758760        for cell_id in self.gidlist: 
    759761            cell_id.hocname = "%s.o(%d)" % (self.hoc_label, self.gidlist.index(cell_id)) 
     762        self._local_ids = self.gidlist 
    760763 
    761764    def __getitem__(self, addr): 
     
    11021105        hoc_comment("--- Population[%s].__randomInit()__ ---" %self.label) 
    11031106        self.rset("v_init", rand_distr) 
    1104      
    1105     def describe(self): 
    1106         """ 
    1107         Return a human readable description of the population" 
    1108         """ 
    1109         print "\n------- Population description -------" 
    1110         print "Population called %s is made of %d cells [%d being local]" %(self.label, len(self.fullgidlist), len(self.gidlist)) 
    1111         print "-> Cells are aranged on a %dD grid of size %s" %(len(self.dim), self.dim) 
    1112         print "-> Celltype is %s" %self.celltype 
    1113         print "-> Cell Parameters used for cell[0] (during initialization and now) are: "  
    1114         for key, value in self.cellparams.items(): 
    1115           print "\t|", key, "\t: ", "init->", value, "\t now->", getattr(self.cell[0],key) 
    1116         print "--- End of Population description ----" 
    11171107 
    11181108 
  • trunk/src/neuron2/__init__.py

    r413 r414  
    132132        cell_parameters = param_dict 
    133133    first_id = simulator.state.gid_counter 
    134     last_id = simulator.state.gid_counter + n 
    135     all_ids = numpy.array([id for id in range(first_id, last_id)], ID) 
     134    last_id = simulator.state.gid_counter + n - 1 
     135    all_ids = numpy.array([id for id in range(first_id, last_id+1)], ID) 
    136136    # mask_local is used to extract those elements from arrays that apply to the cells on the current node 
    137137    mask_local = all_ids%num_processes()==0 # round-robin distribution of cells between nodes 
     
    268268        simulator.initializer.register(self) 
    269269        Population.nPop += 1 
    270         logging.info(self.describe('Creating Population "%(label)s" of shape %(dim)s, '+ 
    271                                    'containing `%(celltype)s`s with indices between %(first_id)s and %(last_id)s')) 
     270        logging.info(self.describe('Creating Population "$label" of shape $dim, '+ 
     271                                   'containing `$celltype`s with indices between $first_id and $last_id')) 
    272272        logging.debug(self.describe()) 
    273273     
     
    333333            raise common.InvalidDimensionsError 
    334334        return coords 
     335 
     336    def index(self, n): 
     337        """Return the nth cell in the population (Indexing starts at 0).""" 
     338        if hasattr(n, '__len__'): 
     339            n = numpy.array(n) 
     340        return self._all_ids.flatten()[n] 
    335341 
    336342    def get(self, parameter_name, as_array=False): 
     
    530536        return float(n_spikes)/n_rec 
    531537 
    532     def describe(self, template=None): 
    533         if template is None: 
    534             rows = ['==== Population %(label)s ====', 
    535                     'Dimensions: %(dim)s', 
    536                     'Cell type: %(celltype)s', 
    537                     'ID range: %(first_id)d-%(last_id)d', 
    538                     'First cell on this node:', 
    539                     '  ID: %(local_first_id)d', 
    540                     '  Parameters: %(cell_parameters)s'] 
    541             template = "\n".join(rows) 
    542         context = self.__dict__.copy() 
    543         first_id = self._local_ids[0] 
    544         context.update(local_first_id=first_id) 
    545         context.update(cell_parameters=first_id.get_parameters()) 
    546         context.update(celltype=self.celltype.__class__.__name__) 
    547         return template % context 
    548      
    549  
     538 
     539         
    550540class Projection(common.Projection): 
    551541    """