Changeset 455

Show
Ignore:
Timestamp:
09/01/08 18:35:57 (3 months ago)
Author:
apdavison
Message:

Started refactoring to give a more object-oriented, easy-to-use approach

Files:

Legend:

Unmodified
Added
Removed
Modified
Copied
Moved
  • doc/poster/trunk/poster.py

    r453 r455  
    6565    return styles 
    6666 
    67 def print_logo(filename, position, y, f_height, maxwidth=None): 
    68     global poster, pagewidth 
    69     if maxwidth is None: 
    70         maxwidth=pagewidth/10.0 
    71     logo = PIL.Image.open(filename) 
    72     logo_height = 0.9*f_height 
    73     hw_ratio = float(logo.size[1])/logo.size[0] 
    74     logo_width = min(maxwidth, logo_height/hw_ratio) 
    75     logo_height = logo_width*hw_ratio 
    76     y = y + (f_height-logo_height)/2.0 
    77     if position == 'left': 
    78         x = 2*margins['left'] 
    79     else: 
    80         x = pageright-logo_width-margins['right'] 
    81     poster.drawInlineImage(logo, x, y, height=logo_height, width=logo_width) 
    82  
    83 def make_title(styles,title,authors,institutions,logo_left,logo_right): 
    84     """Returns the y position of the bottom of the title (including bottom margin).""" 
    85     global poster, margins, pageheight, pagewidth, pagetop 
    86     title_frame = Frame(margins['left'], pageheight/2.0, pagewidth, 20*cm, 
    87                         showBoundary=True) 
    88     author_str = ", ".join([str(a) for a in authors]) 
    89     inst_str = ", ".join(["<super>%d</super>%s" % (i+1,inst) for i, inst in enumerate(institutions)]) 
    90      
    91     title_paragraph = Paragraph(title, styles['Title']) 
    92     p_width = 10*cm 
    93     title_paragraph.wrap(p_width, 1e12) 
    94     while len(title_paragraph.breakLines([p_width,1e12]).lines) > 1: 
    95        p_width *= 1.1 
    96      
    97     title_components = [title_paragraph, 
    98                         Paragraph(author_str, styles['Authors']), 
    99                         Paragraph(inst_str, styles['Affiliations']) 
    100                        ] 
    101     f_height = 0 
    102     for p in title_components: 
    103         f_height += p.wrap(p_width,pageheight)[1] + p.getSpaceAfter() + p.getSpaceBefore() 
    104      
    105     x = margins['left'] + pagewidth/2.0 - p_width/2.0 
    106     y = pagetop - f_height 
    107      
    108     poster.roundRect(margins['left'],y,pagewidth,f_height,2*cm, fill=1) 
    109     title_frame = Frame(x, y, p_width, f_height, showBoundary=False) 
    110     title_frame.addFromList(title_components, poster) 
    111  
    112     print_logo(logo_left, "left", y, f_height) 
    113     print_logo(logo_right, "right", y, f_height) 
    114  
    115      
    116  
    117     title_bottom = y - titlesep 
    118     return title_bottom 
    119  
    120 def make_text_frame(styles,text,x,y,width,height,_debug): 
     67 
     68 
     69 
     70 
     71def make_text_frame(styles, text, x, y, width, height, _debug): 
    12172    pad = 0.5*cm 
    12273    frame = Frame(x, y - height, width, height, 
     
    12677    poster.roundRect(x,y-height,width,height,1*cm,fill=1) 
    12778    paragraph_list = [Paragraph(p, styles['BodyText']) for p in text.split("\n\n")] 
    128     frame.addFromList(paragraph_list, poster) 
    129      
    130  
    131 def make_deflist_frame(styles,definition_list,x,y,width,height,_debug): 
    132     pad = 0.5*cm 
    133     frame = Frame(x, y - height, width, height, 
    134                   leftPadding=pad, rightPadding=pad, bottomPadding=pad, 
    135                   topPadding=pad, showBoundary=_debug) 
    136      
    137     def calc_height(): 
    138         paragraph_list = [Paragraph('<font color="darkgreen"><b>%s</b></font> %s' % item, styles['BodyText']) for item in definition_list] 
    139         f_height = 2*pad 
    140         for p in paragraph_list: 
    141             f_height += p.wrap(width-2*pad,pageheight)[1] + p.getSpaceAfter() + p.getSpaceBefore() 
    142         return f_height 
    143  
    144     while calc_height() > height: 
    145         scale_style(styles['BodyText'], 0.99) 
    146     styles['BodyText'].alignment = TA_JUSTIFY # otherwise we get a 'bad align' error 
    147      
    148     paragraph_list = [Paragraph('<font color="darkgreen"><b>%s</b></font> %s' % item, styles['BodyText']) for item in definition_list] 
    149      
    150     poster.roundRect(x,y-height,width,height,1*cm,fill=1) 
    15179    frame.addFromList(paragraph_list, poster) 
    15280     
     
    278206    return output 
    279207 
    280 def make_example(styles,x_r,y,width,height,_debug=False): 
    281     """ Make a frame showing the VAbenchmarks.py script, together with figure.""" 
    282     global poster 
    283     styles['Title'].alignment = TA_LEFT 
    284     styles['Code'].leftIndent = 0 
    285     checkout_pyNN() 
    286     f = open(os.path.join('pyNN_%s' % VERSION,'test','VAbenchmarks.py'),'r') 
    287     example_script = f.read() 
    288     f.close() 
    289     lines = example_script.split('\n') 
    290     nlines = len(lines) 
    291     maxlength = 0 
    292     for line in lines: 
    293         if len(line) > maxlength: 
    294             maxlength = len(line) 
    295     example_script = colourize(example_script) 
    296      
    297     scale_style(styles['Code'], 10.0/styles['Code'].fontSize) 
    298      
    299     pad = 0.5*cm 
    300     code_flowable = XPreformatted(example_script, styles['Code']) 
    301      
    302     paragraph_list = [Paragraph("Example", styles['Title']), 
    303                       code_flowable] 
    304  
    305     code_height = styles['Code'].leading+styles['Code'].spaceAfter+styles['Code'].spaceBefore 
    306     f_height = nlines * code_height 
    307     f_height += styles['Title'].leading + styles['Title'].spaceBefore + styles['Title'].spaceAfter 
    308     f_height /= 2.0 
    309      
    310     lines_in_first_frame = int(nlines - f_height/code_height) 
    311     maxlength = 0 
    312     for line in lines[:lines_in_first_frame]: 
    313         if len(line) > maxlength: 
    314             maxlength = len(line) 
    315     f_width1 = stringWidth("m"*maxlength, styles['Code'].fontName, styles['Code'].fontSize, 'UTF-8') + pad 
    316     maxlength = 0 
    317     for line in lines[lines_in_first_frame:]: 
    318         if len(line) > maxlength: 
    319             maxlength = len(line) 
    320     f_width2 = stringWidth("m"*maxlength, styles['Code'].fontName, styles['Code'].fontSize, 'UTF-8') + pad 
    321     f_height += 2*pad 
    322  
    323     x = x_r - f_width1 - f_width2 
    324  
    325     poster.roundRect(x,y-f_height,f_width1+f_width2,f_height,1*cm,fill=1) 
    326     frame1 = Frame(x, y-f_height, f_width1, f_height, showBoundary=_debug, 
    327                           leftPadding=pad, rightPadding=0, bottomPadding=pad, 
    328                           topPadding=pad) 
    329     frame1.add(Paragraph("Example", styles['Title']), poster) 
    330     flowables = frame1.split(code_flowable, poster) 
    331      
    332     frame1.addFromList(flowables, poster) 
    333     frame2 = Frame(x + f_width1, y-f_height, f_width2, f_height, showBoundary=_debug, 
    334                           leftPadding=pad, rightPadding=pad, bottomPadding=pad, 
    335                           topPadding=pad) 
    336     frame2.addFromList(flowables, poster) 
    337     #frame3 = Frame(x + 2*f_width, y-f_height, f_width, f_height, showBoundary=_debug, 
    338     #                      leftPadding=0, rightPadding=pad, bottomPadding=pad, 
    339     #                      topPadding=pad) 
    340     #frame3.addFromList(flowables, poster) 
    341  
    342      
    343     return x, y-f_height, f_width1+f_width2,f_height 
    344  
    345 def make_example_figure(filename,x,y,width,height,_debug=False): 
    346     global poster 
    347     pad = 0.5*cm 
    348     img = Image(filename, width=width-2*pad, height=height-2*pad, kind='proportional', lazy=0) 
    349     f_height = img.drawHeight + 2*pad 
    350     figure_frame = Frame(x, y-f_height, 
    351                          width, f_height, 
    352                          showBoundary=_debug, 
    353                          leftPadding=pad, rightPadding=pad, 
    354                          bottomPadding=pad, topPadding=pad) 
    355     #poster.roundRect(x,y-f_height,width,f_height,1*cm) 
    356     figure_frame.add(img, poster) 
    357  
    358208def make_example_figure_caption(caption,x,y,width,height,_debug=False): 
    359209    global poster 
     
    417267    poster.restoreState() 
    418268 
    419 def paint_background(background, photo_credit=None): 
    420     global poster 
    421     try: # first assume it is a colour 
    422         poster.setFillColor(getattr(colors,background)) 
    423         poster.rect(0,0,poster._pagesize[0],poster._pagesize[1],fill=1,stroke=0) 
    424         poster.setFillColor(colors.white) 
    425     except AttributeError: 
    426         # now assume it is an image 
    427         img = Image(background, width=poster._pagesize[0], height=poster._pagesize[1]) 
    428         img.drawOn(poster,0,0) 
    429         if photo_credit: 
    430             poster.saveState() 
    431             poster.translate(poster._pagesize[0],0) 
    432             poster.rotate(90.0) 
    433             poster.setFont("Helvetica-Bold", 24) 
    434             poster.drawString(10,10,photo_credit) 
    435             poster.restoreState() 
    436  
     269 
     270 
     271class Column(object): 
     272     
     273    def __init__(self, left, width): 
     274        self.left = left 
     275        self.width = width 
     276        self.bottom = 0 
     277         
     278class Poster(Canvas): 
     279     
     280    def __init__(self, filename, ncol, 
     281                 pagesize=landscape(A0), 
     282                 margins={'left':2*cm, 'right':2*cm, 'top':2*cm, 'bottom':2*cm}, 
     283                 colsep=2*cm): 
     284        Canvas.__init__(self, filename, pagesize=pagesize, pageCompression=False, verbosity=2) 
     285        self.margins = margins 
     286        self.pagewidth = self._pagesize[0] - margins['left'] - margins['right'] 
     287        self.pageheight = self._pagesize[1] - margins['bottom'] - margins['top'] 
     288        self.pagetop = self._pagesize[1] - margins['top'] 
     289        self.pageright = self._pagesize[0] - margins['right'] 
     290        self.pagebottom = self.pagetop + self.pageheight 
     291        self.setFillColor(colors.white) 
     292        self.setStrokeColor(colors.white) 
     293        self.ncol = ncol 
     294        self.colsep = colsep 
     295        self.colwidth = (self.pagewidth - (ncol-1)*self.colsep)/float(ncol) 
     296        self.columns = [] 
     297        for i in range(ncol): 
     298            self.columns.append(Column(self.margins['left']+i*(self.colwidth+self.colsep), self.colwidth)) 
     299        self.debug = False 
     300         
     301    def set_metadata(self, authors, institutions, title, subject=''): 
     302        self.setAuthor(", ".join([a.name for a in authors])) 
     303        self.setTitle(title) 
     304        self.setSubject(subject) 
     305 
     306    def paint_background(self, background, credit=None): 
     307        try: # first assume it is a colour 
     308            self.setFillColor(getattr(colors, background)) 
     309            self.rect(0, 0, self._pagesize[0], self._pagesize[1], fill=1, stroke=0) 
     310            self.setFillColor(colors.white) 
     311        except AttributeError: 
     312            # now assume it is an image 
     313            img = Image(background, width=self._pagesize[0], height=self._pagesize[1]) 
     314            img.drawOn(self, 0, 0) 
     315            if credit: 
     316                self.saveState() 
     317                self.translate(self._pagesize[0],0) 
     318                self.rotate(90.0) 
     319                self.setFont("Helvetica-Bold", 24) 
     320                self.drawString(10, 10, credit) 
     321                self.restoreState() 
     322     
     323    def make_title(self, styles, title, authors, institutions, logo_left, logo_right): 
     324        """Returns the y position of the bottom of the title (including bottom margin).""" 
     325        title_frame = Frame(self.margins['left'], self.pageheight/2.0, self.pagewidth, 20*cm, 
     326                            showBoundary=True) 
     327        author_str = ", ".join([str(a).replace(' ','&nbsp;') for a in authors]) 
     328        inst_str = ", ".join(["<super>%d</super>%s" % (i+1,inst.replace(' ','&nbsp;')) for i, inst in enumerate(institutions)]) 
     329         
     330        title_paragraph = Paragraph(title, styles['Title']) 
     331        p_width = 10*cm 
     332        title_paragraph.wrap(p_width, 1e12) 
     333        while len(title_paragraph.breakLines([p_width,1e12]).lines) > 1: 
     334           p_width *= 1.1 
     335         
     336        title_components = [title_paragraph, 
     337                            Paragraph(author_str, styles['Authors']), 
     338                            Paragraph(inst_str, styles['Affiliations']) 
     339                           ] 
     340        f_height = 0 
     341        for p in title_components: 
     342            f_height += p.wrap(p_width, self.pageheight)[1] + p.getSpaceAfter() + p.getSpaceBefore() 
     343         
     344        x = self.margins['left'] + self.pagewidth/2.0 - p_width/2.0 
     345        y = self.pagetop - f_height 
     346         
     347        self.roundRect(self.margins['left'], y, self.pagewidth, f_height, 2*cm, fill=1) 
     348        title_frame = Frame(x, y, p_width, f_height, showBoundary=False) 
     349        title_frame.addFromList(title_components, self) 
     350     
     351        self.print_logo(logo_left, "left", y, f_height) 
     352        self.print_logo(logo_right, "right", y, f_height)       
     353     
     354        self.title_bottom = y - titlesep 
     355        self.colheight = self.title_bottom - self.margins['bottom'] 
     356        for column in self.columns: 
     357            column.bottom = self.title_bottom 
     358         
     359        return self.title_bottom 
     360     
     361    def print_logo(self, filename, position, y, f_height, maxwidth=None): 
     362        if maxwidth is None: 
     363            maxwidth=self.pagewidth/10.0 
     364        logo = PIL.Image.open(filename) 
     365        logo_height = 0.9*f_height 
     366        hw_ratio = float(logo.size[1])/logo.size[0] 
     367        logo_width = min(maxwidth, logo_height/hw_ratio) 
     368        logo_height = logo_width*hw_ratio 
     369        y = y + (f_height-logo_height)/2.0 
     370        if position == 'left': 
     371            x = 2*self.margins['left'] 
     372        else: 
     373            x = self.pageright-logo_width-self.margins['right'] 
     374        poster.drawInlineImage(logo, x, y, height=logo_height, width=logo_width) 
     375     
     376    def add_frame(self, column_number, styles, content, height, _debug=False): 
     377        pad = 0.5*cm 
     378        column = self.columns[column_number] 
     379        x = column.left 
     380        y = column.bottom 
     381        width = column.width 
     382        frame = Frame(x, y - height, width, height, 
     383                      leftPadding=pad, rightPadding=pad, bottomPadding=pad, 
     384                      topPadding=pad, showBoundary=_debug) 
     385         
     386        definition_list = content 
     387        def calc_height(): 
     388            paragraph_list = [Paragraph('<font color="darkgreen"><b>%s</b></font> %s' % item, styles['BodyText']) for item in definition_list] 
     389            f_height = 2*pad 
     390            for p in paragraph_list: 
     391                f_height += p.wrap(width-2*pad, self.pageheight)[1] + p.getSpaceAfter() + p.getSpaceBefore() 
     392            return f_height 
     393     
     394        while calc_height() > height: 
     395            scale_style(styles['BodyText'], 0.99) 
     396        styles['BodyText'].alignment = TA_JUSTIFY # otherwise we get a 'bad align' error 
     397         
     398        paragraph_list = [Paragraph('<font color="darkgreen"><b>%s</b></font> %s' % item, styles['BodyText']) for item in definition_list] 
     399         
     400        self.roundRect(x,y-height,width,height,1*cm,fill=1) 
     401        frame.addFromList(paragraph_list, self) 
     402        column.bottom -= height 
     403         
     404    def make_footer(self, text, fontsize=24, color=colors.white): 
     405        self.setFillColor(color) # white works better with a background image 
     406        self.setFont("Helvetica", fontsize)   # bold works better with a background image 
     407        self.drawCentredString(self.margins['left']+self.pagewidth/2.0, 
     408                               0.2*self.margins['bottom'], text) 
     409     
     410    def make_example(self, column_number, styles, height, _debug=False): #,x_r,y,width,height,_debug=False): 
     411        """ Make a frame showing the VAbenchmarks.py script, together with figure.""" 
     412        pad = 0.5*cm 
     413        column = self.columns[column_number] 
     414        x_r = column.left + self.colwidth 
     415        y = column.bottom 
     416        width = self.colwidth 
     417         
     418        styles['Title'].alignment = TA_LEFT 
     419        styles['Code'].leftIndent = 0 
     420        checkout_pyNN() 
     421        f = open(os.path.join('pyNN_%s' % VERSION,'test','VAbenchmarks.py'),'r') 
     422        example_script = f.read() 
     423        f.close() 
     424        lines = example_script.split('\n') 
     425        nlines = len(lines) 
     426        maxlength = 0 
     427        for line in lines: 
     428            if len(line) > maxlength: 
     429                maxlength = len(line) 
     430        example_script = colourize(example_script) 
     431         
     432        scale_style(styles['Code'], 10.0/styles['Code'].fontSize) 
     433         
     434        code_flowable = XPreformatted(example_script, styles['Code']) 
     435         
     436        paragraph_list = [Paragraph("Example", styles['Title']), 
     437                          code_flowable] 
     438     
     439        code_height = styles['Code'].leading+styles['Code'].spaceAfter+styles['Code'].spaceBefore 
     440        f_height = nlines * code_height 
     441        f_height += styles['Title'].leading + styles['Title'].spaceBefore + styles['Title'].spaceAfter 
     442        f_height /= 2.0 
     443         
     444        lines_in_first_frame = int(nlines - f_height/code_height) 
     445        maxlength = 0 
     446        for line in lines[:lines_in_first_frame]: 
     447            if len(line) > maxlength: 
     448                maxlength = len(line) 
     449        f_width1 = stringWidth("m"*maxlength, styles['Code'].fontName, styles['Code'].fontSize, 'UTF-8') + pad 
     450        maxlength = 0 
     451        for line in lines[lines_in_first_frame:]: 
     452            if len(line) > maxlength: 
     453                maxlength = len(line) 
     454        f_width2 = stringWidth("m"*maxlength, styles['Code'].fontName, styles['Code'].fontSize, 'UTF-8') + pad 
     455        f_height += 2*pad 
     456     
     457        x = x_r - f_width1 - f_width2 
     458     
     459        self.roundRect(x,y-f_height,f_width1+f_width2,f_height,1*cm,fill=1) 
     460        frame1 = Frame(x, y-f_height, f_width1, f_height, showBoundary=_debug, 
     461                              leftPadding=pad, rightPadding=0, bottomPadding=pad, 
     462                              topPadding=pad) 
     463        frame1.add(Paragraph("Example", styles['Title']), self) 
     464        flowables = frame1.split(code_flowable, self) 
     465         
     466        frame1.addFromList(flowables, self) 
     467        frame2 = Frame(x + f_width1, y-f_height, f_width2, f_height, showBoundary=_debug, 
     468                              leftPadding=pad, rightPadding=pad, bottomPadding=pad, 
     469                              topPadding=pad) 
     470        frame2.addFromList(flowables, self) 
     471        #frame3 = Frame(x + 2*f_width, y-f_height, f_width, f_height, showBoundary=_debug, 
     472        #                      leftPadding=0, rightPadding=pad, bottomPadding=pad, 
     473        #                      topPadding=pad) 
     474        #frame3.addFromList(flowables, self) 
     475        column.bottom -= f_height 
     476        return x, y-f_height, f_width1+f_width2,f_height 
     477     
     478    def add_figure_frame(self, column_number, filename, caption='', _debug=False): 
     479        pad = 0.5*cm 
     480        column = self.columns[column_number] 
     481        x = column.left 
     482        y = column.bottom 
     483        width = self.colwidth 
     484        img = PIL.Image.open(filename) 
     485        height = img.size[1]*width/img.size[0] 
     486        img = Image(filename, width=width-2*pad, height=height-2*pad, kind='proportional', lazy=0) 
     487        f_height = img.drawHeight + 2*pad 
     488        figure_frame = Frame(x, y-f_height, 
     489                             width, f_height, 
     490                             showBoundary=_debug, 
     491                             leftPadding=pad, rightPadding=pad, 
     492                             bottomPadding=pad, topPadding=pad) 
     493        poster.roundRect(x, y-f_height, width, f_height, 1*cm, fill=1) 
     494        column.bottom -= height 
     495        figure_frame.add(img, self) 
     496     
    437497# ============================================================================== 
    438498 
    439499if __name__ == "__main__": 
    440     VERSION = "0.4" 
    441     FILENAME = "poster_incf2008.pdf" 
    442     svnpath = "https://neuralensemble.kip.uni-heidelberg.de/svn/PyNN/branches/%s" % VERSION 
    443     DEBUG = False 
    444      
    445     TITLE = "PyNN: Towards a universal neural simulator API in Python" 
    446      
    447     INSTITUTIONS = ["UNIC, CNRS, Gif-sur-Yvette, France", 
    448                     "INCM, CNRS, Marseille, France", 
    449                     "Neurobiology and Biophysics, Albert-Ludwigs-University Freiburg, Freiburg, Germany", 
    450                     "Kirchhoff Institute for Physics, University of Heidelberg, Heidelberg, Germany"] 
    451      
    452     AUTHORS = [Author("Andrew Davison", 1), 
    453                Author("Pierre Yger", 1), 
    454                Author("Jens Kremkow", 2,3), 
    455                Author("Laurent Perrinet", 2), 
    456                Author("Eilif Muller", 4)] 
    457      
    458     SUBJECT = "Poster for CNS*2007, Toronto, Canada" 
    459      
    460     ABSTRACT = """Trends in programming language development and adoption point to Python as the high-level systems 
    461     integration language of choice. Python leverages a vast developer-base external to the neuroscience 
    462     community, and promises leaps in simulation complexity and maintainability to any neural simulator 
    463     that adopts it. PyNN [<a href="http://neuralensemble.org/PyNN">http://neuralensemble.org/PyNN</a>] strives to provide a uniform application programming 
    464     interface (API) across neural simulators. Presently NEURON, NEST and PCSIM are supported, and support for 
    465     other simulators, NeuroML output and neuromorphic VLSI hardware is under development. 
    466      
    467     With PyNN it is possible to write a simulation script once and run it without modification on any 
    468     supported simulator. It is also possible to write a script that uses capabilities specific to a single 
    469     simulator. While this sacrifices simulator-independence, is adds flexibility, and can be a useful step in 
    470     porting models between simulators. The design goals of PyNN include allowing access to low-level 
    471     details of a simulation where necessary, while providing the capability to model at a high level of 
    472     abstraction, with concomitant gains in development speed and simulation maintainability. 
    473      
    474     Another of our aims with PyNN is to increase the productivity of neuroscience modeling, by making it 
    475     faster to develop models <i>de novo</i>, by promoting code sharing and reuse across simulator communities, 
    476     and by making it much easier to debug, test and validate simulations by running them on more than one 
    477     simulator. Modelers would then become free to devote more software development effort to 
    478     innovation, building on the simulator core with new tools such as network topology databases, stimulus 
    479     programming, analysis and visualization tools, and simulation accounting. The resulting, community- 
    480     developed 'meta-simulator' system would then represent a powerful tool for overcoming the so-called 
    481     <i>complexity bottleneck</i> that is presently a major roadblock for neural modeling. 
    482     """ 
    483      
    484     QA = [("What is PyNN?", "A Python package that defines and implements a uniform 'application programming interface' (API) across neural simulators. In other words, you can <b>write your simulation script <i>once</i>, then run it <i>without modification</i> on any supported simulator</b> (currently NEURON, NEST and PCSIM)."), 
    485           ("I use simulator <i>X</i>. Why should I switch to PyNN?", "Increased productivity. The main aim of PyNN is to increase the productivity of neuronal network modeling, by making it <b>faster to develop models</b> <i>de novo</i>, by <b>promoting code sharing and reuse</b> across simulator communities, and by making it much <b>easier to debug, test and validate simulations by running them on more than one simulator</b>. Even if you're not interested in using multiple simulators, if you don't already use Python or another dynamic, object-oriented language, and if your simulator doesn't already support programming using abstractions above the level of individual neurons and synaptic connections, you should see major gains from using a more powerful language and from more readable, shorter, more easily-maintainable code."), 
    486            ("Why Python?", 'Most simulators use configuration files or have their own specific scripting language. These are inevitably less powerful and flexible than a general-purpose programming language such as Python. Furthermore, Python has a huge standard library ("batteries included"), excellent numerical and graphical packages (making it an excellent Matlab replacement), a large developer-base outside the neuroscience community, and is free software.'), 
    487            ("I have a model written for simulator <i>X</i>. How do I convert it to PyNN?", "If <i>X</i> already has a Python interface (NEURON, NEST, PCSIM), first convert the code to Python (e.g. in NEURON, replace your hoc code with Python code) then gradually replace simulator-specific code with PyNN code, all the time checking that the model still runs and gives the same results. If <i>X</i> does not have a Python interface, contact us! We would be happy to work with you on adding support for <i>X</i> to PyNN, whether this is through a direct Python interface or a code-generation tool."), 
    488            ("Where can I download PyNN?", "http://neuralensemble.org/PyNN"), 
    489            ("What other solutions are there for developing simulator-independent models?", "<b>NeuroML</b> (http://neuroml.org) is a standard for model specification in XML. <b>NeuroConstruct</b> (http://neuroconstruct.org) is a tool for developing network models, using a graphical interface, that can then be exported as either NEURON or GENESIS code. There is also some overlap with <b>Neurospaces</b> (http://www.neurospaces.org/), a framework for modular construction of computational neuroscience simulators."), 
    490            ("What are your future plans for PyNN?", "We are currently working on: (i) support for NEST version 2, which adds support for distributed (parallel) simulations (distributed simulations in NEURON and PCSIM are already supported); (ii) support for the VLSI analog spiking network hardware being developed within the FACETS project (iii) support for import/export of network models specified in NeuroML; (iv) various improvements/extensions to the API, (v) general performance improvements."), 
    491            ("Why shouldn't I use PyNN?", "(i) If your work does not involve network modelling; (ii) if you prefer to use a graphical interface to develop your simulations."), 
    492            ("Who is using PyNN now?", "PyNN was first developed within the FACETS project, an EC-funded consortium of fifteen or so European research groups including seven groups doing computational neuroscience, using six simulators between them. In the absence of agreement that everyone should use the same simulator, a tool to make it easier to share models between groups was needed, and PyNN was born. Within FACETS, PyNN is being used for simulations of large-scale models of primary visual cortex and of generic cortical circuits with synaptic plasticity. We would like to encourage wider use, and anyone interested in using or developing PyNN should check out http://neuralensemble.org.") 
    493          ] 
    494      
    495     ACKNOWLEDGEMENTS = "This work is supported by the European Commission through the FACETS project (contract number FP6-2004-IST-FETPI-15879) and by the CNRS. PY is supported by a MENRT bursary." 
    496      
    497     CAPTIONS = { 
    498         'VAbenchmark_CUBA_exc.png': """<b>Results of running the CUBA benchmark script</b> (see Box: 'Example'), written in PyNN, with three different simulators (from left to right: NEURON, NEST, PCSIM). 
    499          
    500         The <b><i>top row</i></b> shows the <b><i>membrane potential traces</i></b> for two of the excitatory neurons in the network. 
    501         The <b><i>second row</i></b> shows the <b><i>raster plots</i></b> for the first 320 excitatory neurons in the network (total network size 3200 excitatory and 800 inhibitory neurons). Each dot represents one spike. Each row is a different cell. 
    502         The <b><i>third row</i></b> shows histograms of <b><i>interspike intervals</i></b> (ISIs) for the excitatory and inhibitory sub-populations. 
    503         The <b><i>bottom row</i></b> shows histograms of the <b><i>coefficient of variation (CV) of the ISI</i></b>. 
    504          
    505         For NEST and NEURON, the same sequence of random numbers was used to generate the network connectivity (using a PyNN <font face="Courier">NumpyRNG</font> object. For PCSIM, the random numbers were generated within the simulator (represented in PyNN with a <font face="Courier">NativeRNG</font> object). 
    506          
    507         <b>Even when using exactly the same connectivity pattern, the membrane potential trajectories diverge<b> after about the first 100 ms, although the <b>pattern of mean activity</b> across the network is <b>well preserved</b> between simulators. 
    508          
    509         With a different random connectivity (but with the same connection probability), there is no similarity in detailed activity patterns, but the <b>statistical behaviour of the network</b> in terms of spike train variability <b>is the same</b>.""" 
    510     } 
    511          
     500    execfile("incf2008.py") 
    512501         
    513502    main_font = 'Helvetica' 
    514     margins = {'left':2*cm, 'right':2*cm, 'top':2*cm, 'bottom':2*cm} 
    515503    colsep = 2*cm 
    516504    titlesep = 2*cm 
    517      
    518     ##base_fontSize = 36 
    519     ##styles = getStyleSheet(36, 8) 
    520  
    521     poster = Canvas(FILENAME, 
    522                 pagesize=landscape(A0), 
    523                 pageCompression=False, 
    524                 verbosity=2) 
    525     poster.setAuthor(", ".join([a.name for a in AUTHORS])) 
    526     poster.setTitle(TITLE) 
    527     poster.setSubject(SUBJECT) 
    528  
    529     pagewidth = poster._pagesize[0] - margins['left'] - margins['right'] 
    530     pageheight = poster._pagesize[1] - margins['bottom'] - margins['top'] 
    531     pagetop = poster._pagesize[1] - margins['top'] 
    532     pageright = poster._pagesize[0] - margins['right'] 
    533      
    534     poster.setFillColor(colors.white) 
    535     poster.setStrokeColor(colors.white) 
     505 
     506    poster = Poster(FILENAME, ncol=3) 
     507    poster.set_metadata(AUTHORS, TITLE, SUBJECT) 
     508    poster.paint_background(BACKGROUND['img'], credit=BACKGROUND['credit']) 
    536509  
    537     #paint_background('white') #'seagreen' 'whitesmoke' 'oldlace 
    538      
    539     paint_background('flickr_fortinbras_10182754_cfc533d350.jpg', photo_credit="Background image: 'Pine bough', from http://www.flickr.com/photos/fortinbras") 
    540      
    541     #paint_background('flickr_blmurch_144285136_a7116060ed_o.jpg', photo_credit="Background image: 'Pine cones' by Beatrice Murch (http://www.flickr.com/people/blmurch/)") 
    542      
    543     #paint_background('flickr_blmurch_384758012_cab7208c79_o.jpg', photo_credit="Background image: 'Pine cones on the ceiling' by Beatrice Murch (http://www.flickr.com/people/blmurch/") 
    544      
    545     title_bottom = make_title(getStyleSheet(36, 72), TITLE, AUTHORS, INSTITUTIONS, "pynn_tree2.png", "facetslogoweb.gif") 
    546     # logos 
    547     institution_logos = ['facetslogoweb.gif','logo-cnrs.jpg','bccn-logo.jpg','kip_logo.gif'] 
    548     ncol = 3 
    549     colwidth = (pagewidth - (ncol-1)*colsep)/float(ncol) 
    550     colheight = title_bottom - margins['bottom'] 
     510    title_bottom = poster.make_title(getStyleSheet(36, 72), TITLE, AUTHORS, INSTITUTIONS, "pynn_tree2.png", "facetslogoweb.gif") 
     511     
    551512    #huge_url(poster._pagesize[0]/2.0, title_bottom/2.0, pagewidth) 
    552513     
    553     print "--- Making API docs ---" 
    554     apiwidth = 0.25*pagewidth 
    555     x_api,y_api,w_api,h_api = make_apidocs(getStyleSheet(9,36),margins['left']+pagewidth-apiwidth, title_bottom, apiwidth, 
    556                  colheight, DEBUG) 
     514#    print "--- Making API docs ---" 
     515#    apiwidth = 0.25*poster.pagewidth 
     516#    x_api,y_api,w_api,h_api = make_apidocs(getStyleSheet(9,36),poster.margins['left']+poster.pagewidth-apiwidth, poster.title_bottom, apiwidth, 
     517#                 poster.colheight, DEBUG) 
    557518     
    558519    #make_users_guide(getStyleSheet(15),margins['left']+colwidth+colsep, title_bottom, colwidth, colheight, DEBUG) 
     520    x_api = poster.columns[2].left 
     521     
     522    poster.add_figure_frame(1, "architecture_of_PyNN_v0.5.png", DEBUG) 
    559523     
    560524    print "--- Making example figure ---" 
    561     x_ex,y_ex,w_ex,h_ex = make_example(getStyleSheet(10.5,36), x_api-colsep, title_bottom, colwidth, colheight, DEBUG) 
    562      
    563     make_fancy_box(x_ex, margins['bottom'],w_ex+colsep+w_api,w_ex,y_ex-colsep-margins['bottom'],y_api-colsep-margins['bottom']) 
    564     make_example_figure("VAbenchmark_CUBA_exc.png", x_ex, y_ex-colsep, w_ex, y_ex-colsep-margins['bottom'], DEBUG) 
    565     print "--- Making caption ---" 
    566     make_example_figure_caption(CAPTIONS["VAbenchmark_CUBA_exc.png"], x_api-colsep, y_api-colsep, w_api+colsep, y_api-colsep-margins['bottom'], DEBUG) 
     525    x_ex,y_ex,w_ex,h_ex = poster.make_example(1, getStyleSheet(10.5,36), poster.colheight, DEBUG) 
     526     
     527#    make_fancy_box(x_ex, margins['bottom'],w_ex+colsep+w_api,w_ex,y_ex-colsep-margins['bottom'],y_api-colsep-margins['bottom']) 
     528    poster.add_figure_frame(1, "VAbenchmark_CUBA_exc.png", DEBUG) 
     529#    print "--- Making caption ---" 
     530#    make_example_figure_caption(CAPTIONS["VAbenchmark_CUBA_exc.png"], x_api-colsep, y_api-colsep, w_api+colsep, y_api-colsep-margins['bottom'], DEBUG) 
    567531     
    568532    print "--- Adding QA ---" 
    569     make_deflist_frame(getStyleSheet(36, 72),QA, margins['left'], title_bottom, x_ex-margins['left']-colsep, colheight, DEBUG) 
    570  
    571     #poster.setFillColor(colors.black) # white works better with a background image 
    572     poster.setFont("Helvetica", 24)   # bold works better with a background image 
    573     poster.drawCentredString(margins['left']+pagewidth/2.0, 0.2*margins['bottom'], ACKNOWLEDGEMENTS) 
     533    poster.add_frame(0, styles=getStyleSheet(36, 72), content=QA, height=poster.colheight) 
     534    #make_deflist_frame(getStyleSheet(36, 72),QA, margins['left'], title_bottom, x_ex-margins['left']-colsep, colheight, DEBUG) 
     535 
     536    poster.make_footer(ACKNOWLEDGEMENTS) 
    574537 
    575538    print "--- Saving poster ---"