Ticket #55 (assigned enhancement)

Opened 8 months ago

Last modified 4 months ago

Add `describe()` method to `Population`, `Projection` and other PyNN classes

Reported by: apdavison Assigned to: apdavison (accepted)
Priority: minor Milestone: 0.5.0
Component: common Version: trunk
Keywords: Cc:

Description

The describe() method would return a human-readable description of the object, summarizing type, label, component members, parameter values (including range, mean, etc if these are heterogeneous).

The idea behind this is to make it easier to spot bugs in your (and PyNN's) code, to spot obvious differences between what you think you've built and what has actually been built.

The syntax I have in mind is something along the lines of:

describe(self, template=default_template, renderer=default_renderer)

where renderer should be an object with a render(data, template) method. [describe() calls render() with the provided template and a data dict, and returns the string returned by render()].

This will give the flexibility to easily tune the output (level of verbosity, format (plain text, HTML, XML, JSON)) without having to modify the describe() method itself.

Change History

04/09/08 14:10:55 changed by apdavison

07/16/08 10:00:32 changed by apdavison

  • status changed from new to assigned.

Partially done in r414.

After experimenting with various different templating tools, I decided just to go for the simple templating in the built-in string module. The complexity of supporting multiple, or arbitrary, templating tools seemed to outweigh any benefits (the main limitations of string templates are lack of logic within the templates and inability to descend an object hierarchy (e.g. $a.b.c)).

For reference, here is an example of using a more complex describe() implementation which has a fill attribute (the method returns fill(template, context):

import sys
import Cheetah.Template
import django.template
import django.conf
django.conf.settings.configure()
import cherrytemplate

sim_name = sys.argv[1]

exec('from pyNN.%s import *' % sim_name)

setup()

p1 = Population((5,5), IF_curr_exp)

prj = Projection(p1, p1, AllToAllConnector())

simple_template = """
==== Population %(label)s ====
  Dimensions: %(dim)s
  Cell type: %(celltype)s
  ID range: %(first_id)d-%(last_id)d
  First cell on this node:
    ID: %(local_first_id)d
    Parameters: %(cell_parameters)s
"""

cheetah_template = """
==== Population $label ====
  Dimensions: $dim
  Cell type: $celltype
  ID range: $first_id-$last_id
  First cell on this node:
    ID: $local_first_id
    #for $name,$value in $cell_parameters.items()
    $name: $value
    #end for
"""

django_template = """
==== Population {{label}} ====
  Dimensions: {{dim}}
  Cell type: {{celltype}}
  ID range: {{first_id}}-{{last_id}}
  First cell on this node:
    ID: {{local_first_id}}
    {% for name,value in cell_parameters.items %}{{name}}: {{value}}
    {% endfor %}
"""

cherry_template = """
==== Population <py-eval="label"> ====
  Dimensions: <py-eval="str(dim)">
  Cell type: <py-eval="celltype">
  ID range: <py-eval="str(first_id)">-<py-eval="str(last_id)">
  First cell on this node:
    ID: <py-eval="str(local_first_id)">
    <py-for="name,value in cell_parameters.items()"><py-eval="name">: <py-eval="str(value)">
    </py-for>
"""

print 'Simple'
print p1.describe(template=simple_template, fill=lambda t,c: t % c)
print 'Cheetah'
print p1.describe(template=cheetah_template, fill=lambda t,c: Cheetah.Template.Template(t, searchList=[c]))
print 'Django'
print p1.describe(template=django_template, fill=lambda t,c: django.template.Template(t).render(django.template.Context(c)))
print 'Cherry'
print p1.describe(template=cherry_template, fill=lambda t,c: cherrytemplate.renderTemplate(t, loc=c))

The implementation still needs to be fleshed out, i.e. extend the range of information that is returned by describe().