IPython-fu: el camino de la "nbconversión".

1. El notebook the IPython.

¿Qué es el notebook the IPython?

The goal of IPython is to create a comprehensive environment for interactive and exploratory computing.

Una herramienta para contar historias:

  • metodologías
  • procedimientos
  • análisis

Técnicamente es una documento basado de JSON:

In [1]:
from IPython.nbformat import current
with open('IPython_fu_talk.ipynb') as f:
    nb = current.read(f,'json')
    
nb.worksheets[0].cells[15:20]
Out[1]:
[{u'cell_type': u'markdown',
  u'metadata': {u'slideshow': {u'slide_type': u'fragment'}},
  u'source': u'* Colaborativo'},
 {u'cell_type': u'markdown',
  u'metadata': {u'internals': {u'slide_helper': u'subslide_end'},
   u'slide_helper': u'slide_end',
   u'slideshow': {u'slide_type': u'fragment'}},
  u'source': u'* Abierto'},
 {u'cell_type': u'heading',
  u'level': 2,
  u'metadata': {u'internals': {u'slide_helper': u'subslide_end',
    u'slide_type': u'subslide'},
   u'slide_helper': u'subslide_end',
   u'slideshow': {u'slide_type': u'slide'}},
  u'source': u'2. Instalando el notebook de IPython.'},
 {u'cell_type': u'markdown',
  u'metadata': {u'internals': {u'slide_helper': u'subslide_end',
    u'slide_type': u'subslide'},
   u'slide_helper': u'subslide_end',
   u'slideshow': {u'slide_type': u'subslide'}},
  u'source': u'**\xbfQu\xe9 necesito para hacerlo andar?**\n\n* Tornado\n* ZeroMQ/PyZMQ\n* Jinja2\n* Chrome, Firefox, Safari (WebSockets, Flexible Box Model)\n* Matplotlib para hacer figuras\n* En linux, mac `pip install ipython[all]` o desde el `source` en **github**.\n* Instalaci\xf3n f\xe1cil (incluyendo instaladores para win): Canopy, Anaconda, Python XY, WinPython, Pyzo\n* Online: Wakari'},
 {u'cell_type': u'markdown',
  u'metadata': {u'slideshow': {u'slide_type': u'subslide'}},
  u'source': u"**\xbfC\xf3mo lo hago andar?**\n\n* `cd` en el directorio conteniendo los archivos `ipynb` y simplemente tipeamos:\n\n```\n(ipython_dev)damian@damian-Inspiron-1110:~$ ipython notebook\n\n2013-05-10 12:11:26.912 [NotebookApp] Using existing profile dir: u'/home/damian/.config/ipython/profile_default'\n2013-05-10 12:11:26.937 [NotebookApp] Using MathJax from CDN: http://cdn.mathjax.org/mathjax/latest/MathJax.js\n2013-05-10 12:11:26.984 [NotebookApp] The port 8888 is already in use, trying another random port.\n2013-05-10 12:11:26.985 [NotebookApp] Serving notebooks from local directory: /home/damian\n2013-05-10 12:11:26.985 [NotebookApp] The IPython Notebook is running at: http://127.0.0.1:8888/\n2013-05-10 12:11:26.986 [NotebookApp] Use Control-C to stop this server and shut down all kernels.\nSe ha abierto una nueva ventana en la sesi\xf3n actual del navegador.\n```"}]
  • Genera archivos con la extensión .ipynb que se guardan en el directorio local.
  • En el notebook podemos almacenar:
    • Código
    • Texto (Markdown)
    • Equaciones (LaTeX)
    • Imágenes
    • Videos
    • HTML
  • Puede ser controlado por versiones.
  • Puede verse sin tener IPython instalado usando NBViewer: http://nbviewer.ipython.org/.
  • Puede ser exportado a otros formatos: Slides, HTML, Markdown, reStructured Text, LaTeX y PDF.

¿Cuáles son sus características principales?

  • Interactivo
  • Exploratorio
  • Colaborativo
  • Abierto

2. Instalando el notebook de IPython.

¿Qué necesito para hacerlo andar?

  • Tornado
  • ZeroMQ/PyZMQ
  • Jinja2
  • Chrome, Firefox, Safari (WebSockets, Flexible Box Model)
  • Matplotlib para hacer figuras
  • En linux, mac pip install ipython[all] o desde el source en github.
  • Instalación fácil (incluyendo instaladores para win): Canopy, Anaconda, Python XY, WinPython, Pyzo
  • Online: Wakari

¿Cómo lo hago andar?

  • cd en el directorio conteniendo los archivos ipynb y simplemente tipeamos:
(ipython_dev)damian@damian-Inspiron-1110:~$ ipython notebook

2013-05-10 12:11:26.912 [NotebookApp] Using existing profile dir: u'/home/damian/.config/ipython/profile_default'
2013-05-10 12:11:26.937 [NotebookApp] Using MathJax from CDN: http://cdn.mathjax.org/mathjax/latest/MathJax.js
2013-05-10 12:11:26.984 [NotebookApp] The port 8888 is already in use, trying another random port.
2013-05-10 12:11:26.985 [NotebookApp] Serving notebooks from local directory: /home/damian
2013-05-10 12:11:26.985 [NotebookApp] The IPython Notebook is running at: http://127.0.0.1:8888/
2013-05-10 12:11:26.986 [NotebookApp] Use Control-C to stop this server and shut down all kernels.
Se ha abierto una nueva ventana en la sesión actual del navegador.

Interfase de usuario.

  • Dashboard
  • Menu
  • Barra de herramientas
  • Área del notebook y celdas

Tipo de celdas

  • Code
  • Markdown
  • Raw text
  • Heading

"Shortcuts" del teclado

  • Shift-Enter para ejecutar una celda
  • Ctrl-Enter para ejecutar una celda y quedarse en esa misma celda.
  • Alt-Enter para ejecutar una celda e insertar una nueva celda por debajo de la ejecutada.
  • Todas las otras "shortcuts" tienen la forma: Ctrl-m ?
  • Si querés ver las "shortcuts" disponibles: Ctrl-m h

3. Usando el notebook de IPython.

Trabajar con códido y correrlo:

El clásico hola mundo:

In [2]:
print "Hola PyConAr 2013"
Hola PyConAr 2013

La representación de los objetos es más legible:

In [3]:
from numpy.random import randn
data = {i : randn() for i in range(7)}
data
Out[3]:
{0: -0.6259264547607343,
 1: -1.9360844606050993,
 2: -0.6221479543727583,
 3: -0.7468880564729741,
 4: 0.1075606061430754,
 5: 0.1633988022645425,
 6: 0.25538102234980953}

y contrasten contra la siguiente representación:

In [4]:
>>> from numpy.random import randn
>>> data = {i : randn() for i in range(7)}
>>> print data # pequeña trampa para verlo como se vería en consola
{0: 0.42552225254665826, 1: -0.5582616032586492, 2: -0.5835851552004485, 3: 1.708468060753579, 4: 0.363181597782086, 5: -0.33378775450148057, 6: 0.6321959132378161}

Puedo probar "pedacitos" de código (por ejemplo de tutoriales):

In [5]:
>>> the_world_is_flat = 1
>>> if the_world_is_flat:
...     print "Be careful not to fall off!"
Be careful not to fall off!

In [6]:
In [5]: [x*x for x in range(5)]
Out[6]:
[0, 1, 4, 9, 16]

Puedo ver los errores o tracebacks de una manera simple y visualmente informativa:

In [7]:
%run non_existent_file
ERROR: File `u'non_existent_file.py'` not found.

In [8]:
x = 1
y = 4
z = y/(1-x)
---------------------------------------------------------------------------
ZeroDivisionError                         Traceback (most recent call last)
<ipython-input-8-dc39888fd1d2> in <module>()
      1 x = 1
      2 y = 4
----> 3 z = y/(1-x)

ZeroDivisionError: integer division or modulo by zero

Otras ventajas a la hora de trabajar con código:

  • Completado por Tab
In [9]:
import scipy as sp
In []:
sp.
  • Ayuda integrada
In [10]:
?
In [11]:
def suma(a, b):
    """
    Demo de una función que suma cosas...
    """
    return a + b
In [12]:
suma?
In [13]:
suma??
  • "Atajos" interactivos (aliases, magics)
In [14]:
%magic
In [15]:
%lsmagic
Out[15]:
Available line magics:
%alias  %alias_magic  %autocall  %automagic  %autosave  %bookmark  %cd  %clear  %colors  %config  %connect_info  %debug  %dhist  %dirs  %doctest_mode  %ed  %edit  %env  %gui  %hist  %history  %install_default_config  %install_ext  %install_profiles  %killbgscripts  %less  %load  %load_ext  %loadpy  %logoff  %logon  %logstart  %logstate  %logstop  %lsmagic  %macro  %magic  %man  %matplotlib  %more  %notebook  %page  %pastebin  %pdb  %pdef  %pdoc  %pfile  %pinfo  %pinfo2  %popd  %pprint  %precision  %profile  %prun  %psearch  %psource  %pushd  %pwd  %pycat  %pylab  %qtconsole  %quickref  %recall  %rehashx  %reload_ext  %rep  %rerun  %reset  %reset_selective  %run  %save  %sc  %store  %sx  %system  %tb  %time  %timeit  %unalias  %unload_ext  %who  %who_ls  %whos  %xdel  %xmode

Available cell magics:
%%!  %%HTML  %%SVG  %%bash  %%capture  %%debug  %%file  %%html  %%javascript  %%latex  %%perl  %%prun  %%pypy  %%python  %%python3  %%ruby  %%script  %%sh  %%svg  %%sx  %%system  %%time  %%timeit  %%writefile

Automagic is ON, % prefix IS NOT needed for line magics.
In [16]:
%quickref

Pero tambien tenemos cell magics (%%) a través de las cuales el notebook soporta correr código en otros lenguajes (entre otras tareas:

  • R
  • Octave
  • Cython
  • Bash
  • Perl
  • Ruby
  • etc.

y combinando magics las tareas son muy simples:

In [17]:
%%bash
mkdir temporal/
touch temporal/mi_programa.py
cat temporal/mi_programa.py
In [18]:
%%writefile temporal/mi_programa.py
def mi_funcion(x, y):
    """
    Demo
    """
    return x / y

x = 4
y = 2

resultado = mi_funcion(x, y)
Overwriting temporal/mi_programa.py

In [19]:
%run temporal/mi_programa.py
In [20]:
resultado
Out[20]:
2

Puedo interaccionar fácilmente con el sistema operativo:

In [21]:
!pwd
/media/datos/Desarrollos/pyconar2013_talks

In [22]:
files = !ls
print "My current directory's files:"
print files
My current directory's files:
['figs', 'IPython_fu_talk.ipynb', 'IPython_fu_talk.slides.html', 'README.md', 'soln', 'temporal', 'toggle.tpl']

In [23]:
!echo $files
[figs, IPython_fu_talk.ipynb, IPython_fu_talk.slides.html, README.md, soln, temporal, toggle.tpl]

In [24]:
!echo {files[0].upper()}
FIGS

Por ejemplo, puedo generar figuras programáticamente utilizando matplotlib:

In [25]:
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(0, 3*np.pi, 500)
y = np.sin(x**2)

fig = plt.figure()

axes = fig.add_axes([0.1, 0.1, 0.8, 0.8])

axes.plot(x, y, 'r')

axes.set_xlabel('x')
axes.set_ylabel('sin x^2')
axes.set_title('Una figura simple');

Documentar el flujo de trabajo.

El texto reendea vía Markdown, por ejemplo puedo tener italica, enfásis o linkear a google.

Puedo hacer listas:

  1. primero
  2. segundo
  3. tercero
  • auto
  • biblicleta
  • moto

Puedo embeber código para demostración, por ejemplo, para Python:

def f(x):
    """a docstring"""
    return x**2

o para otros lenguajes:

if (i=0; i<n; i++) {
  printf("hello %d\n", i);
  x += 4;
}

Gracias a MathJax, se pueden incluir expresiones matemáticas inline: \(e^{i\pi} + 1 = 0\) o en bloque:

\[e^x=\sum_{i=0}^\infty \frac{1}{i!}x^i\]

Si el navegador puede mostrarlo...

In [26]:
from IPython.display import display
  • Imágenes:
In [7]:
from IPython.display import Image
Image(filename='pyconar2013_talks/figs/logo.png')
Out[7]:
In [5]:
from IPython.display import SVG
SVG(filename='pyconar2013_talks/figs/python-logo.svg')
Out[5]:
image/svg+xml
  • Video:

Puedo cargar y mostrar videos de Youtube, Vimeo, etc...

In [29]:
from IPython.display import YouTubeVideo
YouTubeVideo('MIAKOMzRl1I')
Out[29]:
  • HTML
In [30]:
from IPython.display import HTML

s = """<table>
<tr>
<th>Header 1</th>
<th>Header 2</th>
</tr>
<tr>
<td>row 1, cell 1</td>
<td>row 1, cell 2</td>
</tr>
<tr>
<td>row 2, cell 1</td>
<td>row 2, cell 2</td>
</tr>
</table>"""
In [31]:
h = HTML(s)
display(h)
Header 1 Header 2
row 1, cell 1 row 1, cell 2
row 2, cell 1 row 2, cell 2
  • Sitios web:
In [32]:
from IPython.display import IFrame
IFrame('http://www.damian.oquanta.info',1024,768)
Out[32]:
  • Música:
In [33]:
%load soln/soundcloud.py

from IPython.display import HTML
h = HTML("""<iframe width="100%" height="166" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=http%3A%2F%2Fapi.soundcloud.com%2Ftracks%2F94543639"></iframe>""")
display(h)
  • Javascript
In [34]:
from IPython.display import Javascript

# fetch d3 from cloudflare
Javascript("""$.getScript('//cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js')""")
Out[34]:
<IPython.core.display.Javascript at 0x2fc0490>
In [35]:
%%html
<style type="text/css">

circle {
  fill: rgb(31, 119, 180);
  fill-opacity: .25;
  stroke: rgb(31, 119, 180);
  stroke-width: 1px;
}

.leaf circle {
  fill: #ff7f0e;
  fill-opacity: 1;
}

text {
  font: 10px sans-serif;
}

</style>
In [37]:
%%javascript

// This unhides the output area
container.show();

// element is the jQuery element we will append to
var e = element.get(0);
    
var diameter = 600,
    format = d3.format(",d");

var pack = d3.layout.pack()
    .size([diameter - 4, diameter - 4])
    .value(function(d) { return d.size; });

var svg = d3.select(e).append("svg")
    .attr("width", diameter)
    .attr("height", diameter)
  .append("g")
    .attr("transform", "translate(2,2)");

d3.json("files/flare.json", function(error, root) {
  var node = svg.datum(root).selectAll(".node")
      .data(pack.nodes)
    .enter().append("g")
      .attr("class", function(d) { return d.children ? "node" : "leaf node"; })
      .attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });

  node.append("title")
      .text(function(d) { return d.name + (d.children ? "" : ": " + format(d.size)); });

  node.append("circle")
      .attr("r", function(d) { return d.r; });

  node.filter(function(d) { return !d.children; }).append("text")
      .attr("dy", ".3em")
      .style("text-anchor", "middle")
      .text(function(d) { return d.name.substring(0, d.r / 3); });
});

d3.select(self.frameElement).style("height", diameter + "px");
<IPython.core.display.Javascript at 0x3bdecd0>

Cargar código remoto

In [38]:
%load http://matplotlib.sourceforge.net/mpl_examples/api/collections_demo.py
In [39]:
#!/usr/bin/env python
'''Demonstration of LineCollection, PolyCollection, and
RegularPolyCollection with autoscaling.

For the first two subplots, we will use spirals.  Their
size will be set in plot units, not data units.  Their positions
will be set in data units by using the "offsets" and "transOffset"
kwargs of the LineCollection and PolyCollection.

The third subplot will make regular polygons, with the same
type of scaling and positioning as in the first two.

The last subplot illustrates the use of "offsets=(xo,yo)",
that is, a single tuple instead of a list of tuples, to generate
successively offset curves, with the offset given in data
units.  This behavior is available only for the LineCollection.

'''

import matplotlib.pyplot as plt
from matplotlib import collections, transforms
from matplotlib.colors import colorConverter
import numpy as np

nverts = 50
npts = 100

# Make some spirals
r = np.array(range(nverts))
theta = np.array(range(nverts)) * (2*np.pi)/(nverts-1)
xx = r * np.sin(theta)
yy = r * np.cos(theta)
spiral = list(zip(xx,yy))

# Make some offsets
rs = np.random.RandomState([12345678])
xo = rs.randn(npts)
yo = rs.randn(npts)
xyo = list(zip(xo, yo))

# Make a list of colors cycling through the rgbcmyk series.
colors = [colorConverter.to_rgba(c) for c in ('r','g','b','c','y','m','k')]

fig, axes = plt.subplots(2,2)
((ax1, ax2), (ax3, ax4)) = axes # unpack the axes


col = collections.LineCollection([spiral], offsets=xyo,
                                transOffset=ax1.transData)
trans = fig.dpi_scale_trans + transforms.Affine2D().scale(1.0/72.0)
col.set_transform(trans)  # the points to pixels transform
    # Note: the first argument to the collection initializer
    # must be a list of sequences of x,y tuples; we have only
    # one sequence, but we still have to put it in a list.
ax1.add_collection(col, autolim=True)
    # autolim=True enables autoscaling.  For collections with
    # offsets like this, it is neither efficient nor accurate,
    # but it is good enough to generate a plot that you can use
    # as a starting point.  If you know beforehand the range of
    # x and y that you want to show, it is better to set them
    # explicitly, leave out the autolim kwarg (or set it to False),
    # and omit the 'ax1.autoscale_view()' call below.

# Make a transform for the line segments such that their size is
# given in points:
col.set_color(colors)

ax1.autoscale_view()  # See comment above, after ax1.add_collection.
ax1.set_title('LineCollection using offsets')


# The same data as above, but fill the curves.
col = collections.PolyCollection([spiral], offsets=xyo,
                                transOffset=ax2.transData)
trans = transforms.Affine2D().scale(fig.dpi/72.0)
col.set_transform(trans)  # the points to pixels transform
ax2.add_collection(col, autolim=True)
col.set_color(colors)


ax2.autoscale_view()
ax2.set_title('PolyCollection using offsets')

# 7-sided regular polygons

col = collections.RegularPolyCollection(7,
                                        sizes = np.fabs(xx)*10.0, offsets=xyo,
                                        transOffset=ax3.transData)
trans = transforms.Affine2D().scale(fig.dpi/72.0)
col.set_transform(trans)  # the points to pixels transform
ax3.add_collection(col, autolim=True)
col.set_color(colors)
ax3.autoscale_view()
ax3.set_title('RegularPolyCollection using offsets')


# Simulate a series of ocean current profiles, successively
# offset by 0.1 m/s so that they form what is sometimes called
# a "waterfall" plot or a "stagger" plot.

nverts = 60
ncurves = 20
offs = (0.1, 0.0)

yy = np.linspace(0, 2*np.pi, nverts)
ym = np.amax(yy)
xx = (0.2 + (ym-yy)/ym)**2 * np.cos(yy-0.4) * 0.5
segs = []
for i in range(ncurves):
    xxx = xx + 0.02*rs.randn(nverts)
    curve = list(zip(xxx, yy*100))
    segs.append(curve)

col = collections.LineCollection(segs, offsets=offs)
ax4.add_collection(col, autolim=True)
col.set_color(colors)
ax4.autoscale_view()
ax4.set_title('Successive data offsets')
ax4.set_xlabel('Zonal velocity component (m/s)')
ax4.set_ylabel('Depth (m)')
# Reverse the y-axis so depth increases downward
ax4.set_ylim(ax4.get_ylim()[::-1])


plt.show()

Reendeo de LaTeX:

In [40]:
from IPython.display import Latex
Latex(r"""\begin{eqnarray}
\nabla \times \vec{\mathbf{B}} -\, \frac1c\, 
\frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\
\nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\
\nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, 
\frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\
\nabla \cdot \vec{\mathbf{B}} & = 0 
\end{eqnarray}""")
Out[40]:
\begin{eqnarray} \nabla \times \vec{\mathbf{B}} -\, \frac1c\, \frac{\partial\vec{\mathbf{E}}}{\partial t} & = \frac{4\pi}{c}\vec{\mathbf{j}} \\ \nabla \cdot \vec{\mathbf{E}} & = 4 \pi \rho \\ \nabla \times \vec{\mathbf{E}}\, +\, \frac1c\, \frac{\partial\vec{\mathbf{B}}}{\partial t} & = \vec{\mathbf{0}} \\ \nabla \cdot \vec{\mathbf{B}} & = 0 \end{eqnarray}

Pandas

In [41]:
import pandas
pandas.set_option('display.notebook_repr_html', True)
In [42]:
%%writefile data.csv
Date,Open,High,Low,Close,Volume,Adj Close
2012-06-01,569.16,590.00,548.50,584.00,14077000,581.50
2012-05-01,584.90,596.76,522.18,577.73,18827900,575.26
2012-04-02,601.83,644.00,555.00,583.98,28759100,581.48
2012-03-01,548.17,621.45,516.22,599.55,26486000,596.99
2012-02-01,458.41,547.61,453.98,542.44,22001000,540.12
2012-01-03,409.40,458.24,409.00,456.48,12949100,454.53
Writing data.csv

In [43]:
df = pandas.read_csv('data.csv')
df
Out[43]:
Date Open High Low Close Volume Adj Close
0 2012-06-01 569.16 590.00 548.50 584.00 14077000 581.50
1 2012-05-01 584.90 596.76 522.18 577.73 18827900 575.26
2 2012-04-02 601.83 644.00 555.00 583.98 28759100 581.48
3 2012-03-01 548.17 621.45 516.22 599.55 26486000 596.99
4 2012-02-01 458.41 547.61 453.98 542.44 22001000 540.12
5 2012-01-03 409.40 458.24 409.00 456.48 12949100 454.53

The IPython kernel/client model

In [44]:
%connect_info
{
  "stdin_port": 48475, 
  "ip": "127.0.0.1", 
  "control_port": 52500, 
  "hb_port": 33886, 
  "signature_scheme": "hmac-sha256", 
  "key": "5e9a6aa9-a8df-4dbf-b84c-f95749413f33", 
  "shell_port": 43361, 
  "transport": "tcp", 
  "iopub_port": 33941
}

Paste the above JSON into a file, and connect with:
    $> ipython <app> --existing <file>
or, if you are local, you can connect with just:
    $> ipython <app> --existing kernel-a70891d2-bb7d-4c82-82d4-829a9883aa7b.json 
or even just:
    $> ipython <app> --existing 
if this is the most recent IPython session you have started.

In [45]:
%qtconsole

4. nbconvert

Intro...

  • NBConvert es una biblioteca de reciente (tech preview) incorporación al núcleo de IPython, y que permite la nbconversión de los notebooks de IPython a otros formatos tales como: html, latex, markdown, python, rst y slides.

  • Esta biblioteca esta basada en el sistema de templates de Jinja, por lo que modificar los nbconversores (o escribir el propio) no debería generar mayores dificultades.

Para utilizarlo desde la linea de comandos:

$ ipython nbconvert <optiones y argumentos>

y para solicitar ayuda:

$ ipython nbconvert --help (y si querés más detalle: --help-all).

In [47]:
%%bash
ipython nbconvert  IPython_fu_talk.ipynb --to html
[NbConvertApp] Using existing profile dir: u'/home/damian/.config/ipython/profile_default'
[NbConvertApp] Converting notebook IPython_fu_talk.ipynb to html
[NbConvertApp] Support files will be in IPython_fu_talk_files/
[NbConvertApp] Loaded template html_full.tpl
[NbConvertApp] Writing 480087 bytes to IPython_fu_talk.html

Slides

Este nbconversor genera una presentacion HTML basada en la popular bibloteca Reveal.js

  • Slides (horizontales).
  • Subslides (verticales).
  • Fragmentos.
  • Transiciones.
  • Temas.
  • Notas.
  • Exportacion a pdf.
In [48]:
%%bash
ipython nbconvert IPython_fu_talk.ipynb --to slides
[NbConvertApp] Using existing profile dir: u'/home/damian/.config/ipython/profile_default'
[NbConvertApp] Converting notebook IPython_fu_talk.ipynb to slides
[NbConvertApp] Support files will be in IPython_fu_talk_files/
[NbConvertApp] Loaded template slides_reveal.tpl
[NbConvertApp] Writing 485430 bytes to IPython_fu_talk.slides.html

Usando la api de nbconvert... para bloguear con IPython y Nikola.

Podemos tomar como ejemplo el plugin ipynb presente en Nikola:

def compile_html(self, source, dest, is_two_file=True):
        if flag is None:
            req_missing(['ipython>=1.0.0'], 'build this site (compile ipynb)')
        makedirs(os.path.dirname(dest))
        HTMLExporter.default_template = 'basic'
        c = Config(self.site.config['IPYNB_CONFIG'])
        exportHtml = HTMLExporter(config=c)
        with codecs.open(dest, "w+", "utf8") as out_file:
            with codecs.open(source, "r", "utf8") as in_file:
                nb = in_file.read()
                nb_json = nbformat.reads_json(nb)
            (body, resources) = exportHtml.from_notebook_node(nb_json)
            out_file.write(body)

5. Discusión.

El notebook de IPython provee toda la infraestructura para:

1- Obtener datos.

2- Procesar los datos obtenidos.

3- Visualizar los datos procesados

4- Elaborar una historia que se sustenta en los datos analizados.

5- Comunicar dicha historia (junto con los datos y las visualizaciones obtenidas).

6. El fututo del notebook the IPython

Para conocer en forma detallada lo lineamientos a futuro:

https://github.com/ipython/ipython/wiki/Roadmap:-IPython

  • Soporte para multiusuarios
  • Soporte para múltiples directorios
  • Widgets interactivos (js)
  • Exportación mejorada de los notebook a otros formatos
  • Modo presentación

Y no se olviden de pasear por la galería de notebooks de IPython disponible en:

https://github.com/ipython/ipython/wiki/A-gallery-of-interesting-IPython-Notebooks