| 21 | | svnpath = "https://neuralensemble.kip.uni-heidelberg.de/svn/PyNN/branches/0.3" |
| 22 | | DEBUG = True |
| 23 | | |
| 24 | | TITLE = "PyNN: Towards a universal neural simulator API in Python" |
| 25 | | |
| 26 | | INSTITUTIONS = ["UNIC, CNRS, Gif-sur-Yvette, France", |
| 27 | | "INCM, CNRS, Marseille, France", |
| 28 | | "Neurobiology and Biophysics, Albert-Ludwigs-University Freiburg, Freiburg, Germany", |
| 29 | | "Kirchhoff Institute for Physics, University of Heidelberg, Heidelberg, Germany"] |
| 30 | | |
| 31 | | AUTHORS = [Author("Andrew Davison", 1), |
| 32 | | Author("Pierre Yger", 1), |
| 33 | | Author("Jens Kremkow", 2,3), |
| 34 | | Author("Laurent Perrinet", 2), |
| 35 | | Author("Eilif Muller", 4)] |
| 36 | | |
| 37 | | SUBJECT = "Poster for CNS*2007, Toronto, Canada" |
| 38 | | |
| 39 | | ABSTRACT = """Trends in programming language development and adoption point to Python as the high-level systems |
| 40 | | integration language of choice. Python leverages a vast developer-base external to the neuroscience |
| 41 | | community, and promises leaps in simulation complexity and maintainability to any neural simulator |
| 42 | | that adopts it. PyNN [<a href="http://neuralensemble.org/PyNN">http://neuralensemble.org/PyNN</a>] strives to provide a uniform application programming |
| 43 | | interface (API) across neural simulators. Presently NEURON, NEST are PCSIM supported, and support for |
| 44 | | other simulators, NeuroML output and neuromorphic VLSI hardware is under development. |
| 45 | | |
| 46 | | With PyNN it is possible to write a simulation script once and run it without modification on any |
| 47 | | supported simulator. It is also possible to write a script that uses capabilities specific to a single |
| 48 | | simulator. While this sacrifices simulator-independence, is adds flexibility, and can be a useful step in |
| 49 | | porting models between simulators. The design goals of PyNN include allowing access to low-level |
| 50 | | details of a simulation where necessary, while providing the capability to model at a high level of |
| 51 | | abstraction, with concomitant gains in development speed and simulation maintainability. |
| 52 | | |
| 53 | | Another of our aims with PyNN is to increase the productivity of neuroscience modeling, by making it |
| 54 | | faster to develop models <i>de novo</i>, by promoting code sharing and reuse across simulator communities, |
| 55 | | and by making it much easier to debug, test and validate simulations by running them on more than one |
| 56 | | simulator. Modelers would then become free to devote more software development effort to |
| 57 | | innovation, building on the simulator core with new tools such as network topology databases, stimulus |
| 58 | | programming, analysis and visualization tools, and simulation accounting. The resulting, community- |
| 59 | | developed 'meta-simulator' system would then represent a powerful tool for overcoming the so-called |
| 60 | | <i>complexity bottleneck</i> that is presently a major roadblock for neural modeling. |
| 61 | | |
| 62 | | This work is supported by the European Union through the FACETS project (contract number FP6- |
| 63 | | 2004-IST-FETPI-15879).""" |
| 64 | | |
| 65 | | main_font = 'Helvetica' |
| 66 | | margins = {'left':2*cm, 'right':2*cm, 'top':2*cm, 'bottom':2*cm} |
| 67 | | colsep = 2*cm |
| 68 | | titlesep = 2*cm |
| 79 | | styles = getSampleStyleSheet() |
| 80 | | # Scale font sizes and related spacing |
| 81 | | for style in styles.byName.values(): |
| 82 | | scale_style(style, 3.6) |
| 83 | | styles['Title'].fontSize += 8 |
| 84 | | |
| 85 | | |
| 86 | | author_style = ParagraphStyle('Authors', parent=styles['Heading3']) |
| 87 | | author_style.alignment = TA_CENTER |
| 88 | | styles.add(author_style) |
| 89 | | |
| 90 | | affiliation_style = ParagraphStyle('Affiliations', parent=styles['Normal']) |
| 91 | | affiliation_style.alignment = TA_CENTER |
| 92 | | styles.add(affiliation_style) |
| 93 | | |
| 94 | | users_guide_style = ParagraphStyle('UsersGuide', parent=styles['BodyText']) |
| 95 | | scale_style(users_guide_style, 2.0/3.6) |
| 96 | | styles.add(users_guide_style) |
| 97 | | |
| 98 | | for style in "Heading1","Heading2","Heading3","Code": |
| 99 | | newstyle = ParagraphStyle('UsersGuide%s' % style, parent=styles[style]) |
| 100 | | scale_style(newstyle, 2.0/3.6) |
| 101 | | styles.add(newstyle) |
| 102 | | |
| 103 | | styles['Title'].alignment = TA_CENTER |
| 104 | | styles['BodyText'].alignment = TA_JUSTIFY |
| 105 | | styles['UsersGuide'].alignment = TA_JUSTIFY |
| 106 | | |
| 107 | | print "Font sizes:" |
| 108 | | for style in 'BodyText','Title', 'Heading1', 'Heading2', 'Heading3', 'UsersGuide': |
| 109 | | print style, styles[style].fontSize |
| 110 | | |
| 111 | | ##styles['UsersGuideCode'].listAttrs() |
| 112 | | |
| 113 | | poster = Canvas("poster_cns2007.pdf", |
| 114 | | pagesize=landscape(A0), |
| 115 | | pageCompression=False, |
| 116 | | verbosity=2) |
| 117 | | poster.setAuthor(", ".join([a.name for a in AUTHORS])) |
| 118 | | poster.setTitle(TITLE) |
| 119 | | poster.setSubject(SUBJECT) |
| 120 | | |
| 121 | | pagewidth = poster._pagesize[0] - margins['left'] - margins['right'] |
| 122 | | pageheight = poster._pagesize[1] - margins['bottom'] - margins['top'] |
| 123 | | pagetop = poster._pagesize[1] - margins['top'] |
| 124 | | pageright = poster._pagesize[0] - margins['right'] |
| 125 | | |
| 126 | | |
| 127 | | title_frame = Frame(margins['left'], pageheight/2.0, pagewidth, 20*cm, |
| 128 | | showBoundary=True) |
| 129 | | |
| 130 | | |
| 131 | | |
| 132 | | author_str = ", ".join([str(a) for a in AUTHORS]) |
| 133 | | inst_str = ", ".join(["<super>%d</super>%s" % (i+1,inst) for i, inst in enumerate(INSTITUTIONS)]) |
| 134 | | |
| 135 | | title_paragraph = Paragraph(TITLE, styles['Title']) |
| 136 | | p_width = 10*cm |
| 137 | | title_paragraph.wrap(p_width, 1e12) |
| 138 | | while len(title_paragraph.breakLines([p_width,1e12]).lines) > 1: |
| 139 | | p_width *= 1.1 |
| 140 | | |
| 141 | | title_components = [title_paragraph, |
| 142 | | Paragraph(author_str, styles['Authors']), |
| 143 | | Paragraph(inst_str, styles['Affiliations']) |
| 144 | | ] |
| 145 | | f_height = 0 |
| 146 | | for p in title_components: |
| 147 | | f_height += p.wrap(p_width,pageheight)[1] + p.getSpaceAfter() + p.getSpaceBefore() |
| 148 | | |
| 149 | | x = margins['left'] + pagewidth/2.0 - p_width/2.0 |
| 150 | | y = pagetop - f_height |
| 151 | | title_frame = Frame(x, y, p_width, f_height, showBoundary=False) |
| 152 | | title_frame.addFromList(title_components, poster) |
| 153 | | |
| 154 | | def print_logo(filename, position, y, f_height, maxwidth=pagewidth/10.0): |
| | 35 | def getStyleSheet(scale_factor): |
| | 36 | styles = getSampleStyleSheet() |
| | 37 | # Scale font sizes and related spacing |
| | 38 | for style in styles.byName.values(): |
| | 39 | scale_style(style, scale_factor) |
| | 40 | styles['Title'].fontSize += 8 |
| | 41 | |
| | 42 | author_style = ParagraphStyle('Authors', parent=styles['Heading3']) |
| | 43 | author_style.alignment = TA_CENTER |
| | 44 | styles.add(author_style) |
| | 45 | |
| | 46 | affiliation_style = ParagraphStyle('Affiliations', parent=styles['Normal']) |
| | 47 | affiliation_style.alignment = TA_CENTER |
| | 48 | styles.add(affiliation_style) |
| | 49 | |
| | 50 | users_guide_style = ParagraphStyle('UsersGuide', parent=styles['BodyText']) |
| | 51 | scale_style(users_guide_style, 1.5/scale_factor) |
| | 52 | styles.add(users_guide_style) |
| | 53 | |
| | 54 | for style in "Heading1","Heading2","Heading3","Code": |
| | 55 | newstyle = ParagraphStyle('UsersGuide%s' % style, parent=styles[style]) |
| | 56 | scale_style(newstyle, 1.5/scale_factor) |
| | 57 | styles.add(newstyle) |
| | 58 | |
| | 59 | styles['Title'].alignment = TA_CENTER |
| | 60 | styles['BodyText'].alignment = TA_JUSTIFY |
| | 61 | styles['UsersGuide'].alignment = TA_JUSTIFY |
| | 62 | |
| | 63 | print "Font sizes:" |
| | 64 | for style in 'BodyText','Title', 'Heading1', 'Heading2', 'Heading3', 'UsersGuide': |
| | 65 | print style, styles[style].fontSize |
| | 66 | ##styles['UsersGuideCode'].listAttrs() |
| | 67 | |
| | 68 | return styles |
| | 69 | |
| | 70 | def print_logo(filename, position, y, f_height, maxwidth=None): |
| | 71 | global poster, pagewidth |
| | 72 | if maxwidth is None: |
| | 73 | maxwidth=pagewidth/10.0 |
| 167 | | |
| 168 | | print_logo("pynn_tree2.png", "left", y, f_height) |
| 169 | | print_logo("facetslogoweb.gif", "right", y, f_height) |
| 170 | | # logos |
| 171 | | institution_logos = ['facetslogoweb.gif','logo-cnrs.jpg','bccn-logo.jpg','kip_logo.gif'] |
| 172 | | |
| 173 | | poster.roundRect(margins['left'],y,pagewidth,f_height,2*cm) |
| 174 | | |
| 175 | | title_bottom = y - titlesep |
| 176 | | |
| 177 | | ncol = 3 |
| 178 | | colwidth = (pagewidth - (ncol-1)*colsep)/float(ncol) |
| 179 | | |
| 180 | | abstract_frame = Frame(margins['left'], title_bottom - pageheight, colwidth, pageheight, |
| 181 | | showBoundary=True) |
| 182 | | |
| 183 | | abstract = [Paragraph(p, styles['BodyText']) for p in ABSTRACT.split("\n\n")] |
| 184 | | #print abstract |
| 185 | | abstract_frame.addFromList(abstract, poster) |
| 186 | | #while not abstract_frame.addFromList(abstract, poster): |
| 187 | | # abstract_frame._height += 1*cm |
| 188 | | # abstract_frame._geom() |
| 189 | | # abstract_frame._reset() |
| 190 | | # print abstract_frame._height |
| 191 | | svn_client = pysvn.Client() |
| 192 | | svn_client.checkout(svnpath, "pyNN") |
| 193 | | import pyNN |
| 194 | | import docutils.core |
| 195 | | |
| 196 | | user_guide_frame = Frame(margins['left']+colwidth+colsep, title_bottom - pageheight, colwidth, pageheight, |
| 197 | | showBoundary=True) |
| 198 | | |
| 199 | | import restxsl.transform |
| 200 | | import re |
| 201 | | paragraph_template = re.compile(r'<para( style="(?P<style>\S.*)")?>(?P<content>.*)</para>') |
| 202 | | |
| 203 | | paragraph_list = [] |
| 204 | | for section in "Installation", : #"Introduction", "Installation", "Low-level API": #, "High-level API": |
| 205 | | filename = "pyNN/doc/" + section.lower().replace("-","").replace(" ","") + ".txt" |
| 206 | | filename, xmltext = restxsl.transform.restxsl(filename, |
| 207 | | smartPunctuation=False, |
| 208 | | encoding='UTF-8', |
| 209 | | xslPath="reST2reportlab.xsl")[0] |
| 210 | | print "*********************** " + section + " ******************************" |
| 211 | | #xmltext = re.sub(u'\N{NON-BREAKING HYPHEN}', r'-', xmltext) |
| 212 | | xmltext = xmltext.replace('â','-') # the first character is a unicode non-breaking hyphen, introduced by restxsl (see restxsl/restxmldoc.py line 234) |
| 213 | | print xmltext |
| 214 | | paragraph_list = [Paragraph(section, styles['UsersGuideHeading1'])] |
| 215 | | for match in paragraph_template.finditer(xmltext): |
| 216 | | groups = match.groupdict() |
| 217 | | content = groups['content'] |
| 218 | | style = "UsersGuide" |
| 219 | | if groups['style'] is not None: |
| 220 | | style += groups['style'] |
| 221 | | print "###### " + style |
| 222 | | print content |
| 223 | | paragraph_list += [Paragraph(content, styles[style])] |
| 224 | | user_guide_frame.addFromList(paragraph_list, poster) |
| 225 | | |
| 226 | | poster.save() |
| | 86 | def make_title(title,authors,institutions,logo_left,logo_right): |
| | 87 | """Returns the y position of the bottom of the title (including bottom margin).""" |
| | 88 | global poster, margins, pageheight, pagewidth, styles, pagetop |
| | 89 | title_frame = Frame(margins['left'], pageheight/2.0, pagewidth, 20*cm, |
| | 90 | showBoundary=True) |
| | 91 | author_str = ", ".join([str(a) for a in authors]) |
| | 92 | inst_str = ", ".join(["<super>%d</super>%s" % (i+1,inst) for i, inst in enumerate(institutions)]) |
| | 93 | |
| | 94 | title_paragraph = Paragraph(title, styles['Title']) |
| | 95 | p_width = 10*cm |
| | 96 | title_paragraph.wrap(p_width, 1e12) |
| | 97 | while len(title_paragraph.breakLines([p_width,1e12]).lines) > 1: |
| | 98 | p_width *= 1.1 |
| | 99 | |
| | 100 | title_components = [title_paragraph, |
| | 101 | Paragraph(author_str, styles['Authors']), |
| | 102 | Paragraph(inst_str, styles['Affiliations']) |
| | 103 | ] |
| | 104 | f_height = 0 |
| | 105 | for p in title_components: |
| | 106 | f_height += p.wrap(p_width,pageheight)[1] + p.getSpaceAfter() + p.getSpaceBefore() |
| | 107 | |
| | 108 | x = margins['left'] + pagewidth/2.0 - p_width/2.0 |
| | 109 | y = pagetop - f_height |
| | 110 | title_frame = Frame(x, y, p_width, f_height, showBoundary=False) |
| | 111 | title_frame.addFromList(title_components, poster) |
| | 112 | |
| | 113 | print_logo(logo_left, "left", y, f_height) |
| | 114 | print_logo(logo_right, "right", y, f_height) |
| | 115 | |
| | 116 | poster.roundRect(margins['left'],y,pagewidth,f_height,2*cm) |
| | 117 | |
| | 118 | title_bottom = y - titlesep |
| | 119 | return title_bottom |
| | 120 | |
| | 121 | def make_abstract(text,x,y,width,height,_debug): |
| | 122 | abstract_frame = Frame(x, y - height, width, height, |
| | 123 | showBoundary=_debug) |
| | 124 | |
| | 125 | abstract = [Paragraph(p, styles['BodyText']) for p in ABSTRACT.split("\n\n")] |
| | 126 | #print abstract |
| | 127 | abstract_frame.addFromList(abstract, poster) |
| | 128 | #while not abstract_frame.addFromList(abstract, poster): |
| | 129 | # abstract_frame._height += 1*cm |
| | 130 | # abstract_frame._geom() |
| | 131 | # abstract_frame._reset() |
| | 132 | # print abstract_frame._height |
| | 133 | |
| | 134 | def make_users_guide(x,y,width,height,_debug=False): |
| | 135 | global poster |
| | 136 | svn_client = pysvn.Client() |
| | 137 | svn_client.checkout(svnpath, "pyNN") |
| | 138 | import pyNN |
| | 139 | import docutils.core |
| | 140 | import restxsl.transform |
| | 141 | import re |
| | 142 | |
| | 143 | user_guide_frame = Frame(x, y - height, width, height, showBoundary=_debug) |
| | 144 | |
| | 145 | paragraph_template = re.compile(r'<para( style="(?P<style>\S*)")?>(?P<content>.*?)</para>',re.DOTALL) |
| | 146 | |
| | 147 | for section in "High-level API", : #"Introduction", "Installation", "Low-level API": #, "High-level API": |
| | 148 | filename = "pyNN/doc/" + section.lower().replace("-","").replace(" ","") + ".txt" |
| | 149 | filename, xmltext = restxsl.transform.restxsl(filename, |
| | 150 | smartPunctuation=False, |
| | 151 | encoding='UTF-8', |
| | 152 | xslPath="reST2reportlab.xsl")[0] |
| | 153 | #if _debug: print "*********************** " + section + " ******************************" |
| | 154 | xmltext = xmltext.replace('â','-') # the first character is a unicode non-breaking hyphen, introduced by restxsl (see restxsl/restxmldoc.py line 234) |
| | 155 | #if _debug: print xmltext |
| | 156 | #if _debug: print "-----------------------------" |
| | 157 | paragraph_list = [Paragraph(section, styles['UsersGuideHeading1'])] |
| | 158 | for match in paragraph_template.finditer(xmltext): |
| | 159 | groups = match.groupdict() |
| | 160 | content = groups['content'] |
| | 161 | style = "UsersGuide" |
| | 162 | if groups['style'] is not None: |
| | 163 | style += groups['style'] |
| | 164 | #if _debug: print "###### " + style |
| | 165 | #if _debug: print content |
| | 166 | paragraph_list += [Paragraph(content, styles[style])] |
| | 167 | user_guide_frame.addFromList(paragraph_list, poster) |
| | 168 | |
| | 169 | # ============================================================================== |
| | 170 | |
| | 171 | if __name__ == "__main__": |
| | 172 | svnpath = "https://neuralensemble.kip.uni-heidelberg.de/svn/PyNN/branches/0.3" |
| | 173 | DEBUG = True |
| | 174 | |
| | 175 | TITLE = "PyNN: Towards a universal neural simulator API in Python" |
| | 176 | |
| | 177 | INSTITUTIONS = ["UNIC, CNRS, Gif-sur-Yvette, France", |
| | 178 | "INCM, CNRS, Marseille, France", |
| | 179 | "Neurobiology and Biophysics, Albert-Ludwigs-University Freiburg, Freiburg, Germany", |
| | 180 | "Kirchhoff Institute for Physics, University of Heidelberg, Heidelberg, Germany"] |
| | 181 | |
| | 182 | AUTHORS = [Author("Andrew Davison", 1), |
| | 183 | Author("Pierre Yger", 1), |
| | 184 | Author("Jens Kremkow", 2,3), |
| | 185 | Author("Laurent Perrinet", 2), |
| | 186 | Author("Eilif Muller", 4)] |
| | 187 | |
| | 188 | SUBJECT = "Poster for CNS*2007, Toronto, Canada" |
| | 189 | |
| | 190 | ABSTRACT = """Trends in programming language development and adoption point to Python as the high-level systems |
| | 191 | integration language of choice. Python leverages a vast developer-base external to the neuroscience |
| | 192 | community, and promises leaps in simulation complexity and maintainability to any neural simulator |
| | 193 | that adopts it. PyNN [<a href="http://neuralensemble.org/PyNN">http://neuralensemble.org/PyNN</a>] strives to provide a uniform application programming |
| | 194 | interface (API) across neural simulators. Presently NEURON, NEST are PCSIM supported, and support for |
| | 195 | other simulators, NeuroML output and neuromorphic VLSI hardware is under development. |
| | 196 | |
| | 197 | With PyNN it is possible to write a simulation script once and run it without modification on any |
| | 198 | supported simulator. It is also possible to write a script that uses capabilities specific to a single |
| | 199 | simulator. While this sacrifices simulator-independence, is adds flexibility, and can be a useful step in |
| | 200 | porting models between simulators. The design goals of PyNN include allowing access to low-level |
| | 201 | details of a simulation where necessary, while providing the capability to model at a high level of |
| | 202 | abstraction, with concomitant gains in development speed and simulation maintainability. |
| | 203 | |
| | 204 | Another of our aims with PyNN is to increase the productivity of neuroscience modeling, by making it |
| | 205 | faster to develop models <i>de novo</i>, by promoting code sharing and reuse across simulator communities, |
| | 206 | and by making it much easier to debug, test and validate simulations by running them on more than one |
| | 207 | simulator. Modelers would then become free to devote more software development effort to |
| | 208 | innovation, building on the simulator core with new tools such as network topology databases, stimulus |
| | 209 | programming, analysis and visualization tools, and simulation accounting. The resulting, community- |
| | 210 | developed 'meta-simulator' system would then represent a powerful tool for overcoming the so-called |
| | 211 | <i>complexity bottleneck</i> that is presently a major roadblock for neural modeling. |
| | 212 | |
| | 213 | This work is supported by the European Union through the FACETS project (contract number FP6- |
| | 214 | 2004-IST-FETPI-15879).""" |
| | 215 | main_font = 'Helvetica' |
| | 216 | margins = {'left':2*cm, 'right':2*cm, 'top':2*cm, 'bottom':2*cm} |
| | 217 | colsep = 2*cm |
| | 218 | titlesep = 2*cm |
| | 219 | styles = getStyleSheet(3.6) |
| | 220 | |
| | 221 | poster = Canvas("poster_cns2007.pdf", |
| | 222 | pagesize=landscape(A0), |
| | 223 | pageCompression=False, |
| | 224 | verbosity=2) |
| | 225 | poster.setAuthor(", ".join([a.name for a in AUTHORS])) |
| | 226 | poster.setTitle(TITLE) |
| | 227 | poster.setSubject(SUBJECT) |
| | 228 | |
| | 229 | pagewidth = poster._pagesize[0] - margins['left'] - margins['right'] |
| | 230 | pageheight = poster._pagesize[1] - margins['bottom'] - margins['top'] |
| | 231 | pagetop = poster._pagesize[1] - margins['top'] |
| | 232 | pageright = poster._pagesize[0] - margins['right'] |
| | 233 | title_bottom = make_title(TITLE, AUTHORS, INSTITUTIONS, "pynn_tree2.png", "facetslogoweb.gif") |
| | 234 | # logos |
| | 235 | institution_logos = ['facetslogoweb.gif','logo-cnrs.jpg','bccn-logo.jpg','kip_logo.gif'] |
| | 236 | ncol = 3 |
| | 237 | colwidth = (pagewidth - (ncol-1)*colsep)/float(ncol) |
| | 238 | make_abstract(ABSTRACT, margins['left'], title_bottom, colwidth, pageheight, DEBUG) |
| | 239 | make_users_guide(margins['left']+colwidth+colsep, title_bottom, colwidth, pageheight, DEBUG) |
| | 240 | |
| | 241 | poster.save() |