##// END OF EJS Templates
Fixed bug when cells do not have associated slideshow metadata. Fixed example_slide.ipynb to use metadata for slides building.
damianavila -
Show More
@@ -1,142 +1,145 b''
1 1 from converters.markdown import ConverterMarkdown
2 2 from IPython.utils.text import indent
3 3 import io
4 4 import os
5 5 import itertools
6 6
7 7 class ConverterReveal(ConverterMarkdown):
8 8 """Convert a notebook to a html slideshow.
9 9
10 10 It generates a static html slideshow based in markdown and reveal.js.
11 11 """
12 12
13 13 def __init__(self, infile, highlight_source=False, show_prompts=True,
14 14 inline_prompt=True):
15 15 super(ConverterMarkdown, self).__init__(infile)
16 16 self.highlight_source = highlight_source
17 17 self.show_prompts = show_prompts
18 18 self.inline_prompt = inline_prompt
19 19
20 20 def switch_meta(self, m_list):
21 21 if len(m_list) > 1:
22 22 if not (len(m_list) == 2 and m_list[1] == [u'new_fragment = True']):
23 23 m_list[0], m_list[1] = m_list[1], m_list[0]
24 24 return m_list
25 25
26 26 def meta2str(self, meta):
27 meta_tuple = meta[u'slideshow'].items()
27 try:
28 meta_tuple = meta[u'slideshow'].items()
29 except KeyError as e:
30 meta_tuple = ()
28 31 meta_list = [[x + ' = ' + unicode(y)] for x, y in meta_tuple]
29 32 meta_list = self.switch_meta(meta_list)
30 33 return u'\n'.join(list(itertools.chain(*meta_list)))
31 34
32 35 def render_heading(self, cell):
33 36 return [self.meta2str(cell.metadata), '{0} {1}'.format('#' * cell.level, cell.source), '']
34 37
35 38 def render_markdown(self, cell):
36 39 return [self.meta2str(cell.metadata), cell.source, '']
37 40
38 41 def render_raw(self, cell):
39 42 if self.raw_as_verbatim:
40 43 return [indent(self.meta2str(cell.metadata)), indent(cell.source), '']
41 44 else:
42 45 return [self.meta2str(cell.metadata), cell.source, '']
43 46
44 47 def convert(self, cell_separator='\n'):
45 48 """
46 49 Generic method to converts notebook to a string representation.
47 50
48 51 This is accomplished by dispatching on the cell_type, so subclasses of
49 52 Convereter class do not need to re-implement this method, but just
50 53 need implementation for the methods that will be dispatched.
51 54
52 55 Parameters
53 56 ----------
54 57 cell_separator : string
55 58 Character or string to join cells with. Default is "\n"
56 59
57 60 Returns
58 61 -------
59 62 out : string
60 63 """
61 64 lines = []
62 65 lines.extend(self.optional_header())
63 66 begin = ['<div class="reveal"><div class="slides">']
64 67 lines.extend(begin)
65 68 slides_list = self.build_slides(cell_separator)
66 69 lines.extend(slides_list)
67 70 end = ['</div></div>']
68 71 lines.extend(end)
69 72 lines.extend(self.optional_footer())
70 73 return u'\n'.join(lines)
71 74
72 75 def build_slides(self, cell_separator='\n'):
73 76 "build the slides from text list"
74 77 text = self.main_body(cell_separator)
75 78 text = [x for x in text if x != u'new_section = False'
76 79 and x != u'new_subsection = False'
77 80 and x != u'new_fragment = False']
78 81 left = '<section data-markdown><script type="text/template">'
79 82 right = '</script></section>'
80 83 slides = [list(x[1]) for x in itertools.groupby(text, lambda x: x==u'new_section = True') if not x[0]]
81 84 for slide in slides:
82 85 slide.insert(0, u'')
83 86 slide.insert(0,left)
84 87 slide.append(right)
85 88 if slide[2] == u'new_subsection = True':
86 89 slide.pop(2)
87 90 slide.insert(0,'<section>')
88 91 slide.append('</section>')
89 92 for i,j in enumerate(slide):
90 93 if j == u'new_subsection = True':
91 94 slide[i] = right + left
92 95 slide.insert(i + 1, u'')
93 96 elif slide[4] == u'new_subsection = True':
94 97 slide[4] = right
95 98 slide.insert(5, u'')
96 99 slide.insert(5,left)
97 100 slide.insert(5,'<section>')
98 101 slide.append('</section>')
99 102 for i,j in enumerate(slide):
100 103 if j == u'new_subsection = True':
101 104 slide[i] = right + left
102 105 slide.insert(i + 1, u'')
103 106 for i,j in enumerate(slide):
104 107 if j == u'new_fragment = True':
105 108 slide[i] = '<p class="fragment">'
106 109 slide[i + 2] = '</p>'
107 110 slide.insert(i + 3, u'')
108 111 return list(itertools.chain(*slides))
109 112
110 113 def save(self, outfile=None, encoding=None):
111 114 "read and parse notebook into self.nb"
112 115 if outfile is None:
113 116 outfile = self.outbase + '_slides.' + 'html'
114 117 if encoding is None:
115 118 encoding = self.default_encoding
116 119 with io.open(outfile, 'w', encoding=encoding) as f:
117 120 f.write(self.output)
118 121 return os.path.abspath(outfile)
119 122
120 123 def template_read(self):
121 124 "read the reveal_template.html"
122 125 here = os.path.split(os.path.realpath(__file__))[0]
123 126 reveal_template = os.path.join(here, '..', 'templates', 'reveal_base.html')
124 127 with io.open(reveal_template, 'r', encoding='utf-8') as f:
125 128 template = f.readlines()
126 129 template = map(lambda s: s.strip(), template) # cosmetic one to get short html files
127 130 return template
128 131
129 132 def template_split(self):
130 133 "split the reveal_template.html in header and footer lists"
131 134 temp = self.template_read()
132 135 splitted_temp = [list(x[1]) for x in itertools.groupby(temp, lambda x: x==u'%slides%') if not x[0]]
133 136 return splitted_temp
134 137
135 138 def optional_header(self):
136 139 optional_header_body = self.template_split()
137 140 return optional_header_body[0]
138 141
139 142 def optional_footer(self):
140 143 optional_footer_body = self.template_split()
141 144 return optional_footer_body[1]
142 145
@@ -1,468 +1,463 b''
1 1 {
2 2 "metadata": {
3 3 "name": "example_slide"
4 4 },
5 5 "nbformat": 3,
6 6 "nbformat_minor": 0,
7 7 "worksheets": [
8 8 {
9 9 "cells": [
10 10 {
11 11 "cell_type": "heading",
12 12 "level": 1,
13 "metadata": {},
13 "metadata": {
14 "slideshow": {
15 "new_section": true
16 }
17 },
14 18 "source": [
15 19 "Notebook Slide Example"
16 20 ]
17 21 },
18 22 {
19 23 "cell_type": "markdown",
20 "metadata": {},
21 "source": [
22 "Rendered by vIPer using [Reveal.js](http://lab.hakim.se/reveal-js)!"
23 ]
24 },
25 {
26 "cell_type": "markdown",
27 "metadata": {},
24 "metadata": {
25 "slideshow": {
26 "new_fragment": false
27 }
28 },
28 29 "source": [
29 "(also you can get a [pdf](http://www.slideviper.oquanta.info/reveal/slides.pdf) version with chrome!)"
30 "Rendered by nbconvert using [Reveal.js](http://lab.hakim.se/reveal-js)!"
30 31 ]
31 32 },
32 33 {
33 34 "cell_type": "markdown",
34 "metadata": {},
35 "metadata": {
36 "slideshow": {
37 "new_fragment": true
38 }
39 },
35 40 "source": [
36 "##<<<"
41 "by Dami\u00e1n Avila"
37 42 ]
38 43 },
39 44 {
40 45 "cell_type": "heading",
41 46 "level": 2,
42 "metadata": {},
47 "metadata": {
48 "slideshow": {
49 "new_section": true,
50 "new_subsection": true
51 }
52 },
43 53 "source": [
44 54 "NOTE: This notebook was modified from a Fernando's one"
45 55 ]
46 56 },
47 57 {
48 58 "cell_type": "markdown",
49 59 "metadata": {},
50 60 "source": [
51 61 "Since the notebook was introduced with [IPython 0.12](http://ipython.org/ipython-doc/rel-0.12.1/whatsnew/version0.12.html), it has proved to be very popular, and we are seeing great adoption of the tool and the underlying file format in research and education. One persistent question we've had since the beginning (even prior to its official release) was whether it would be possible to easily write blog posts using the notebook."
52 62 ]
53 63 },
54 64 {
55 65 "cell_type": "markdown",
56 "metadata": {},
57 "source": [
58 "##---"
59 ]
60 },
61 {
62 "cell_type": "markdown",
63 "metadata": {},
66 "metadata": {
67 "slideshow": {
68 "new_subsection": true
69 }
70 },
64 71 "source": [
65 72 "The combination of easy editing in markdown with the notebook's ability to contain code, figures and results, makes it an ideal platform for quick authoring of technical documents, so being able to post to a blog is a natural request."
66 73 ]
67 74 },
68 75 {
69 76 "cell_type": "markdown",
70 "metadata": {},
71 "source": [
72 "##---"
73 ]
74 },
75 {
76 "cell_type": "markdown",
77 "metadata": {},
77 "metadata": {
78 "slideshow": {
79 "new_subsection": true
80 }
81 },
78 82 "source": [
79 83 "Today, in answering a query about this from a colleague, I decided to try again the status of our conversion pipeline, and I'm happy to report that with a bit of elbow-grease, at least on Blogger things work pretty well! \n",
80 84 "\n",
81 85 "This post was *entirely* written as a notebook, and in fact I have now created a [github repo](https://github.com/fperez/blog), which means that you can see it directly [rendered in IPyhton's nbviewer app](http://nbviewer.ipython.org/urls/raw.github.com/fperez/blog/master/120907-Blogging with the IPython Notebook.ipynb)."
82 86 ]
83 87 },
84 88 {
85 "cell_type": "markdown",
86 "metadata": {},
87 "source": [
88 "##>>><<<"
89 ]
90 },
91 {
92 89 "cell_type": "heading",
93 90 "level": 2,
94 "metadata": {},
91 "metadata": {
92 "slideshow": {
93 "new_section": true,
94 "new_subsection": true
95 }
96 },
95 97 "source": [
96 98 "Converting your notebook to html with nbconvert"
97 99 ]
98 100 },
99 101 {
100 102 "cell_type": "markdown",
101 103 "metadata": {},
102 104 "source": [
103 105 "The first thing you will need is our [nbconvert](https://github.com/ipython/nbconvert) tool that converts notebooks across formats. The README file in the repo contains the requirements for nbconvert (basically [python-markdown](http://pypi.python.org/pypi/Markdown/), [pandoc](http://johnmacfarlane.net/pandoc), [docutils from SVN](http://docutils.svn.sourceforge.net/viewvc/docutils/trunk/docutils/?view=tar) and [pygments](http://pygments.org)).\n",
104 106 "\n",
105 107 "Once you have nbconvert installed, you can convert your notebook to Blogger-friendly html with:\n",
106 108 "\n",
107 109 " nbconvert -f blogger-html your_notebook.ipynb"
108 110 ]
109 111 },
110 112 {
111 113 "cell_type": "markdown",
112 "metadata": {},
113 "source": [
114 "##---"
115 ]
116 },
117 {
118 "cell_type": "markdown",
119 "metadata": {},
114 "metadata": {
115 "slideshow": {
116 "new_subsection": true
117 }
118 },
120 119 "source": [
121 120 "This will leave two files in your computer, one named `your_notebook.html` and one named `your_noteboook_header.html`; it might also create a directory called `your_notebook_files` if needed for ancillary files. The first file will contain the body of your post and can be pasted wholesale into the Blogger editing area. The second file contains the CSS and Javascript material needed for the notebook to display correctly, you should only need to use this once to configure your blogger setup (see next):"
122 121 ]
123 122 },
124 123 {
125 124 "cell_type": "markdown",
126 "metadata": {},
127 "source": [
128 "##---"
129 ]
130 },
131 {
132 "cell_type": "markdown",
133 "metadata": {},
125 "metadata": {
126 "slideshow": {
127 "new_subsection": true
128 }
129 },
134 130 "source": [
135 131 " # Only one notebook so far\n",
136 132 " (master)longs[blog]> ls\n",
137 133 " 120907-Blogging with the IPython Notebook.ipynb fig/ old/\n",
138 134 "\n",
139 135 " # Now run the conversion:\n",
140 136 " (master)longs[blog]> nbconvert.py -f blogger-html 120907-Blogging\\ with\\ the\\ IPython\\ Notebook.ipynb\n",
141 137 " \n",
142 138 " # This creates the header and html body files\n",
143 139 " (master)longs[blog]> ls\n",
144 140 " 120907-Blogging with the IPython Notebook_header.html fig/\n",
145 141 " 120907-Blogging with the IPython Notebook.html old/\n",
146 142 " 120907-Blogging with the IPython Notebook.ipynb"
147 143 ]
148 144 },
149 145 {
150 "cell_type": "markdown",
151 "metadata": {},
152 "source": [
153 "##>>><<<"
154 ]
155 },
156 {
157 146 "cell_type": "heading",
158 147 "level": 2,
159 "metadata": {},
148 "metadata": {
149 "slideshow": {
150 "new_section": true,
151 "new_subsection": true
152 }
153 },
160 154 "source": [
161 155 "Configuring your Blogger blog to accept notebooks"
162 156 ]
163 157 },
164 158 {
165 159 "cell_type": "markdown",
166 160 "metadata": {},
167 161 "source": [
168 162 "The notebook uses a lot of custom CSS for formatting input and output, as well as Javascript from [MathJax](http://www.mathjax.org) to display mathematical notation. You will need all this CSS and the Javascript calls in your blog's configuration for your notebook-based posts to display correctly:"
169 163 ]
170 164 },
171 165 {
172 166 "cell_type": "markdown",
173 "metadata": {},
167 "metadata": {
168 "slideshow": {
169 "new_fragment": true,
170 "new_subsection": true
171 }
172 },
174 173 "source": [
175 "##---"
174 "* Once authenticated, go to your blog's overview page by clicking on its title.\n",
175 "\n",
176 "\n"
176 177 ]
177 178 },
178 179 {
179 180 "cell_type": "markdown",
180 "metadata": {},
181 "metadata": {
182 "slideshow": {
183 "new_fragment": true
184 }
185 },
181 186 "source": [
182 "1. Once authenticated, go to your blog's overview page by clicking on its title.\n",
183 "2. Click on templates (left column) and customize using the Advanced options.\n",
184 "3. Scroll down the middle column until you see an \"Add CSS\" option.\n",
185 "4. Copy entire the contents of the `_header` file into the CSS box."
187 "* Click on templates (left column) and customize using the Advanced options."
186 188 ]
187 189 },
188 190 {
189 191 "cell_type": "markdown",
190 "metadata": {},
192 "metadata": {
193 "slideshow": {
194 "new_fragment": true
195 }
196 },
191 197 "source": [
192 "##---"
198 "* Scroll down the middle column until you see an \"Add CSS\" option."
193 199 ]
194 200 },
195 201 {
196 202 "cell_type": "markdown",
197 "metadata": {},
203 "metadata": {
204 "slideshow": {
205 "new_fragment": true
206 }
207 },
198 208 "source": [
199 "That's it, and you shouldn't need to do anything else as long as the CSS we use in the notebooks doesn't drastically change. This customization of your blog needs to be done only once.\n",
200 "\n",
201 "While you are at it, I recommend you change the width of your blog so that cells have enough space for clean display; in experimenting I found out that the default template was too narrow to properly display code cells, producing a lot of text wrapping that impaired readability. I ended up using a layout with a single column for all blog contents, putting the blog archive at the bottom. Otherwise, if I kept the right sidebar, code cells got too squished in the post area."
209 "* Copy entire the contents of the `_header` file into the CSS box."
202 210 ]
203 211 },
204 212 {
205 213 "cell_type": "markdown",
206 "metadata": {},
214 "metadata": {
215 "slideshow": {
216 "new_subsection": true
217 }
218 },
207 219 "source": [
208 "##---"
220 "That's it, and you shouldn't need to do anything else as long as the CSS we use in the notebooks doesn't drastically change. This customization of your blog needs to be done only once.\n",
221 "\n",
222 "While you are at it, I recommend you change the width of your blog so that cells have enough space for clean display; in experimenting I found out that the default template was too narrow to properly display code cells, producing a lot of text wrapping that impaired readability. I ended up using a layout with a single column for all blog contents, putting the blog archive at the bottom. Otherwise, if I kept the right sidebar, code cells got too squished in the post area."
209 223 ]
210 224 },
211 225 {
212 226 "cell_type": "markdown",
213 "metadata": {},
227 "metadata": {
228 "slideshow": {
229 "new_subsection": true
230 }
231 },
214 232 "source": [
215 233 "I also had problems using some of the fancier templates available from 'Dynamic Views', in that I could never get inline math to render. But sticking to those from the Simple or 'Picture Window' categories worked fine and they still allow for a lot of customization.\n",
216 234 "\n",
217 235 "*Note:* if you change blog templates, Blogger does destroy your custom CSS, so you may need to repeat the above steps in that case."
218 236 ]
219 237 },
220 238 {
221 "cell_type": "markdown",
222 "metadata": {},
223 "source": [
224 "##>>>"
225 ]
226 },
227 {
228 239 "cell_type": "heading",
229 240 "level": 2,
230 "metadata": {},
241 "metadata": {
242 "slideshow": {
243 "new_section": true
244 }
245 },
231 246 "source": [
232 247 "Adding the actual posts"
233 248 ]
234 249 },
235 250 {
236 251 "cell_type": "markdown",
237 252 "metadata": {},
238 253 "source": [
239 254 "Now, whenever you want to write a new post as a notebook, simply convert the `.ipynb` file to blogger-html and copy its entire contents to the clipboard. Then go to the 'raw html' view of the post, remove anything Blogger may have put there by default, and paste. You should also click on the 'options' tab (right hand side) and select both `Show HTML literally` and `Use <br> tag`, else your paragraph breaks will look all wrong.\n",
240 255 "\n",
241 256 "That's it!"
242 257 ]
243 258 },
244 259 {
245 "cell_type": "markdown",
246 "metadata": {},
247 "source": [
248 "##---"
249 ]
250 },
251 {
252 260 "cell_type": "heading",
253 261 "level": 2,
254 "metadata": {},
262 "metadata": {
263 "slideshow": {
264 "new_section": true
265 }
266 },
255 267 "source": [
256 268 "What can you put in?"
257 269 ]
258 270 },
259 271 {
260 272 "cell_type": "markdown",
261 273 "metadata": {},
262 274 "source": [
263 275 "I will now add a few bits of code, plots, math, etc, to show which kinds of content can be put in and work out of the box. These are mostly bits copied from our [example notebooks](https://github.com/ipython/ipython/tree/master/docs/examples/notebooks) so the actual content doesn't matter, I'm just illustrating the *kind* of content that works."
264 276 ]
265 277 },
266 278 {
267 279 "cell_type": "code",
268 280 "collapsed": false,
269 281 "input": [
270 282 "# Let's initialize pylab so we can plot later\n",
271 283 "%pylab inline"
272 284 ],
273 285 "language": "python",
274 286 "metadata": {},
275 287 "outputs": [
276 288 {
277 289 "output_type": "stream",
278 290 "stream": "stdout",
279 291 "text": [
280 292 "\n",
281 293 "Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].\n",
282 294 "For more information, type 'help(pylab)'.\n"
283 295 ]
284 296 }
285 297 ],
286 298 "prompt_number": 1
287 299 },
288 300 {
289 301 "cell_type": "markdown",
290 "metadata": {},
291 "source": [
292 "##---"
293 ]
294 },
295 {
296 "cell_type": "markdown",
297 "metadata": {},
302 "metadata": {
303 "slideshow": {
304 "new_section": true
305 }
306 },
298 307 "source": [
299 308 "With pylab loaded, the usual matplotlib operations work"
300 309 ]
301 310 },
302 311 {
303 312 "cell_type": "code",
304 313 "collapsed": false,
305 314 "input": [
306 315 "x = linspace(0, 2*pi)\n",
307 316 "plot(x, sin(x), label=r'$\\sin(x)$')\n",
308 317 "plot(x, cos(x), 'ro', label=r'$\\cos(x)$')\n",
309 318 "title(r'Two familiar functions')\n",
310 319 "legend()"
311 320 ],
312 321 "language": "python",
313 322 "metadata": {},
314 323 "outputs": [
315 324 {
316 325 "output_type": "pyout",
317 326 "prompt_number": 2,
318 327 "text": [
319 328 "<matplotlib.legend.Legend at 0xa90d90c>"
320 329 ]
321 330 },
322 331 {
323 332 "output_type": "display_data",
324 333 "png": "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\ncHL/D9ce9mWkzIEYAAAAAElFTkSuQmCC\n"
325 334 }
326 335 ],
327 336 "prompt_number": 2
328 337 },
329 338 {
330 339 "cell_type": "markdown",
331 "metadata": {},
332 "source": [
333 "##---"
334 ]
335 },
336 {
337 "cell_type": "markdown",
338 "metadata": {},
340 "metadata": {
341 "slideshow": {
342 "new_section": true
343 }
344 },
339 345 "source": [
340 346 "The notebook, thanks to MathJax, has great LaTeX support, so that you can type inline math $(1,\\gamma,\\ldots, \\infty)$ as well as displayed equations:\n",
341 347 "\n",
342 348 "$$\n",
343 349 "e^{i \\pi}+1=0\n",
344 350 "$$\n",
345 351 "\n",
346 352 "**(the last equation is beatiful, isn't it?... Dami\u00e1n talking... he he!)**"
347 353 ]
348 354 },
349 355 {
350 "cell_type": "markdown",
351 "metadata": {},
352 "source": [
353 "##<<<"
354 ]
355 },
356 {
357 356 "cell_type": "heading",
358 357 "level": 2,
359 "metadata": {},
358 "metadata": {
359 "slideshow": {
360 "new_section": true,
361 "new_subsection": true
362 }
363 },
360 364 "source": [
361 365 "You can easily include formatted text and code with markdown"
362 366 ]
363 367 },
364 368 {
365 369 "cell_type": "markdown",
366 370 "metadata": {},
367 371 "source": [
368 372 "You can *italicize*, **boldface**\n",
369 373 "\n",
370 374 "* build \n",
371 375 "* lists\n",
372 376 "\n",
373 377 "and embed code meant for illustration instead of execution in Python:\n",
374 378 "\n",
375 379 " def f(x):\n",
376 380 " \"\"\"a docstring\"\"\"\n",
377 381 " return x**2"
378 382 ]
379 383 },
380 384 {
381 385 "cell_type": "markdown",
382 "metadata": {},
383 "source": [
384 "##---"
385 ]
386 },
387 {
388 "cell_type": "markdown",
389 "metadata": {},
386 "metadata": {
387 "slideshow": {
388 "new_subsection": true
389 }
390 },
390 391 "source": [
391 392 "or other languages:\n",
392 393 "\n",
393 394 " if (i=0; i<n; i++) {\n",
394 395 " printf(\"hello %d\\n\", i);\n",
395 396 " x += 4;\n",
396 397 " }"
397 398 ]
398 399 },
399 400 {
400 401 "cell_type": "markdown",
401 402 "metadata": {},
402 403 "source": [
403 404 "**And you also have highlight for your code, hehe! (Dami\u00e1n talking again...)**"
404 405 ]
405 406 },
406 407 {
407 408 "cell_type": "markdown",
408 "metadata": {},
409 "source": [
410 "##>>>"
411 ]
412 },
413 {
414 "cell_type": "markdown",
415 "metadata": {},
409 "metadata": {
410 "slideshow": {
411 "new_section": true
412 }
413 },
416 414 "source": [
417 415 "And since the notebook can store displayed images in the file itself, you can show images which will be embedded in your post:"
418 416 ]
419 417 },
420 418 {
421 419 "cell_type": "markdown",
422 420 "metadata": {},
423 421 "source": [
424 422 "![Image](http://www.bugtreat.com/blog/wp-content/uploads/2012/04/Python-Programming-Language.png)"
425 423 ]
426 424 },
427 425 {
428 "cell_type": "markdown",
429 "metadata": {},
430 "source": [
431 "##---"
432 ]
433 },
434 {
435 426 "cell_type": "heading",
436 427 "level": 1,
437 "metadata": {},
428 "metadata": {
429 "slideshow": {
430 "new_section": true
431 }
432 },
438 433 "source": [
439 434 "IPython rocks!"
440 435 ]
441 436 },
442 437 {
443 438 "cell_type": "markdown",
444 439 "metadata": {},
445 440 "source": [
446 441 "Just my little contribution...\n",
447 442 "\n",
448 443 "I have a lot of work to do but this is an exciting beginning!\n",
449 444 "\n",
450 445 "You can check [vIPer](http://www.viperapp.oquanta.info)."
451 446 ]
452 447 },
453 448 {
454 449 "cell_type": "markdown",
455 450 "metadata": {},
456 451 "source": [
457 452 "And you can find me at:\n",
458 453 "\n",
459 454 "* [@damian_avila](https://twitter.com/damian_avila)\n",
460 455 "* [OQUANTA](http://www.oquanta.info)\n",
461 456 "* [BLOG](http://www.damian.oquanta.info)"
462 457 ]
463 458 }
464 459 ],
465 460 "metadata": {}
466 461 }
467 462 ]
468 463 } No newline at end of file
General Comments 0
You need to be logged in to leave comments. Login now