from IPython.nbformat import current
with open('test_slides.ipynb') as f:
    nb = current.read(f,'json')
    
nb.worksheets[0].cells[18:19]

"""
Explanation: <span class="hgviolet">IPython-fu</span>
<span class="hgpink">El</span> <span class="hgblue">camino</span> <span class="hgorange">de la</span> <span class="hggreen">"nbconversión"</span>
<p style="text-align: center;"><i class="icon-user icon-2x"> [Damián Avila](http://www.damian.oquanta.info)</i></p>

<p style="text-align: center;"><i class="icon-twitter icon-2x"> [@damian_avila](http://twitter.com/damian_avila)</i></p>

<p style="text-align: center;"><i class="icon-github icon-2x"> [damianavila](https://github.com/damianavila)</i></p>

<p style="text-align: center;"><i class="icon-envelope-alt icon-2x"> <a href="mailto:info@oquanta.info">info@oquanta.info</a></i></p>

<p style="text-align: center;"><i class="icon-globe icon-2x"> <a href="http://goo.gl/lwQtB0">http://goo.gl/lwQtB0</a></i></p>

1. El notebook the IPython.
<img src="logo.png" />
<p style="text-align: center;"><i class="icon-globe icon-2x"> <a href="http://ipython.org">http://ipython.org</a></i></p>

¿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:
End of explanation
"""


print "Hola Scipy..."

"""
Explanation: 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:

```bash
(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:
End of explanation
"""


from numpy.random import randn
data = {i : randn() for i in range(10)}
data

"""
Explanation: La representación de los objetos es más legible:
End of explanation
"""


>>> 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

"""
Explanation: y contrasten contra la siguiente representación:
End of explanation
"""


>>> the_world_is_flat = 1
>>> if the_world_is_flat:
...     print "Hello Scipy Conference!"

for x in range(10):
    print(x)

In [5]: [x*x for x in range(7)]

"""
Explanation: Puedo probar "pedacitos" de código (por ejemplo de tutoriales):
End of explanation
"""


%run non_existent_file

x = 1
y = 4
z = y/(1-x)
z

"""
Explanation: Puedo ver los errores o tracebacks de una manera simple y visualmente informativa:
End of explanation
"""


import scipy as sp

sp.  

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

Completado por Tab
End of explanation
"""


?

def suma(a, b):
    """
    Demo de una función que suma cosas...
    """
    return a + b

suma?

suma??

"""
Explanation: Ayuda integrada
End of explanation
"""


%magic

%lsmagic

%quickref

"""
Explanation: "Atajos" interactivos (aliases, magics)
End of explanation
"""


%%bash
mkdir temporal/
touch temporal/mi_programa.py
cat temporal/mi_programa.py

%%writefile temporal/mi_programa.py
def mi_funcion(x, y):
    """
    Demo
    """
    return x / y

x = 4
y = 2

resultado = mi_funcion(x, y)

%run temporal/mi_programa.py

resultado

"""
Explanation: 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:
End of explanation
"""


!pwd

files = !ls
print "My current directory's files:"
print files

!echo $files

!echo {files[0].upper()}

"""
Explanation: Puedo interaccionar fácilmente con el sistema operativo:
End of explanation
"""


%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');

"""
Explanation: Por ejemplo, puedo generar figuras programáticamente utilizando matplotlib:
End of explanation
"""


from IPython.display import display

"""
Explanation: 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:

primero
segundo

tercero


auto

biblicleta
moto

Puedo embeber código para demostración, por ejemplo, para Python:
python
    def f(x):
        """a docstring"""
        return x**2
o para otros lenguajes:
javascript
    if (i=0; i&lt;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...
End of explanation
"""


from IPython.display import Image
Image(filename='logo.png')  

from IPython.display import SVG
SVG(filename='python-logo.svg')

"""
Explanation: Imágenes:
End of explanation
"""


from IPython.display import YouTubeVideo
YouTubeVideo('MIAKOMzRl1I')

"""
Explanation: Video:

Puedo cargar y mostrar videos de Youtube, Vimeo, etc...
End of explanation
"""


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>"""

h = HTML(s)
display(h)

"""
Explanation: HTML
End of explanation
"""


from IPython.display import IFrame
IFrame('http://www.damian.oquanta.info', 800, 600)

"""
Explanation: Sitios web:
End of explanation
"""


%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)

"""
Explanation: Música:
End of explanation
"""


from IPython.display import Javascript

# fetch d3 from cloudflare
Javascript("""$.getScript('//cdnjs.cloudflare.com/ajax/libs/d3/3.2.2/d3.v3.min.js')""")

%%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>

%%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("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");

"""
Explanation: Javascript
End of explanation
"""


%load http://matplotlib.sourceforge.net/mpl_examples/api/collections_demo.py

#!/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()




"""
Explanation: Cargar código remoto
End of explanation
"""


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}""")

"""
Explanation: Reendeo de LaTeX:
End of explanation
"""


import pandas
pandas.set_option('display.notebook_repr_html', True)

%%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

df = pandas.read_csv('data.csv')
df

"""
Explanation: Pandas
End of explanation
"""


%connect_info

%qtconsole

"""
Explanation: The IPython kernel/client model
End of explanation
"""


%%bash
ipython nbconvert  IPython_fu_talk.ipynb --to html

"""
Explanation: 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 &lt;optiones y argumentos&gt;
y para solicitar ayuda: 
$ ipython nbconvert --help (y si querés más detalle: --help-all).
End of explanation
"""


import subprocess

command = "ipython nbconvert test_slides.ipynb --to slides --post serve"
subprocess.Popen(command.split())

"""
Explanation: 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.
End of explanation
"""


IFrame('http://www.damian.oquanta.info/posts/blogging-with-nikola-and-ipython.html', 800, 600)

"""
Explanation: Más info: http://www.damian.oquanta.info/categories/reveal.html
Usando la api de nbconvert... para bloguear con IPython y Nikola.
Podemos tomar como ejemplo el plugin ipynb presente en Nikola:
python
def compile_html(self, source, dest, is_two_file=True):
        if flag is None:
            req_missing(['ipython&gt;=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)
End of explanation
"""


