2. Introducción a JupyterLab

[1]:
import numpy as np
import scipy.integrate

import bokeh.io
import bokeh.plotting
bokeh.io.output_notebook()
Loading BokehJS ...

En esta lección, aprenderás sobre diferentes formas de interactuar con el intérprete de Python y, lo más importante, lo básico sobre cómo usar JupyterLab. Todas tus tareas se entregarán como notebooks de Jupyter, así que esto es algo que necesitarás dominar. Te será útil revisar la introducción a LaTeX para aprender cómo usar \(\LaTeX\) en tus notebooks de Jupyter.

Por supuesto, también deberías leer la documentación oficial de JupyterLab.

Comenzaremos presentando el intérprete de Python.

2.1. El intérprete de Python

Antes de profundizar en el intérprete de Python, quiero recordarte que este curso no está diseñado para enseñarte la sintaxis de Python (aunque la aprenderás). Lo que aprendas aquí te ayudará a entender cómo usar tu computadora para el análisis de datos en general. Piensa en esto así: parte de la misión de este curso es ayudarte a liberar el poder de tu computadora para resolver problemas biológicos. Python es solo el lenguaje de instrucción. Dicho esto, comencemos a hablar de cómo funciona Python.

Python es un lenguaje interpretado, lo que significa que cada línea de código que escribes se traduce, o interpreta, en un conjunto de instrucciones que tu máquina puede entender mediante el intérprete de Python. Esto contrasta con los lenguajes compilados. Para estos lenguajes (los más dominantes son Fortran, C y C++), todo tu código se traduce a lenguaje de máquina antes de ejecutarlo. Cuando ejecutas tu programa, ya está en lenguaje de máquina.

Así que, cada vez que quieras ejecutar tu código Python, se lo das al intérprete de Python.

Hay muchas formas de iniciar el intérprete de Python. Una forma es escribir

python

en la línea de comandos. Esto inicia el intérprete de Python estándar. Realmente no usaremos esto en la clase. Más bien, tendremos una experiencia de Python mucho mejorada, ya sea usando IPython, una versión interactiva y mejorada de Python disponible a través de la consola de JupyterLab, o usando un notebook, también disponible en JupyterLab.

2.2. «Hola, mundo.» y la función print()

Tradicionalmente, el primer programa que alguien escribe al aprender un nuevo lenguaje se llama «Hola, mundo.» En este programa, las palabras «Hola, mundo.» se imprimen en la pantalla. El original fue probablemente escrito por Brian Kernighan, uno de los inventores de Unix y autor del clásico libro sobre el lenguaje C. En su versión original, el texto impreso era «hello, world» (sin punto ni H mayúscula), pero existen muchas variantes.

Primero escribiremos y ejecutaremos este pequeño programa usando una consola de JupyterLab. Después de iniciar JupyterLab, probablemente ya tengas el Launcher en tu ventana de JupyterLab. Si no es así, puedes expandir la pestaña Files a la izquierda de la ventana de JupyterLab (si no está ya expandida) haciendo clic en esa pestaña, o alternativamente presionando ctrl+b (o cmd+b en macOS). En la parte superior de la pestaña Files hay un signo +, que te da acceso al Launcher de Jupyter.

En el Launcher de Jupyter, haz clic en el ícono Python 3 bajo Console. Esto abrirá una consola, que tiene un gran espacio en blanco sobre un prompt que dice In []:. Puedes ingresar código Python en este prompt y se ejecutará.

Para imprimir Hola, mundo., ingresa el siguiente código. Para ejecutarlo, presiona shift+enter.

[ ]:
print('Hola, mundo.')

2.3. Archivos .py

Ahora usemos nuestro nuevo conocimiento de la función print() para que la computadora diga algo más que solo Hola, mundo. Escribe estas líneas en el prompt, presionando enter cada vez que necesites una nueva línea. Después de escribirlas todas, presiona shift+enter para ejecutarlas.

[ ]:
# Las primeras líneas del Zen de Python por Tim Peters
print('Hermoso es mejor que feo.')
print('Explícito es mejor que implícito.')
print('Simple es mejor que complejo.')
print('Complejo es mejor que complicado.')

Nota que la primera línea está precedida por un signo #, y el intérprete de Python la ignora. El signo # denota un comentario, que es ignorado por el intérprete, ¡pero muy importante para los humanos!

Aunque el prompt de la consola fue útil para ingresar todo esto, una mejor opción es guardarlas en un archivo y luego hacer que el intérprete de Python ejecute las líneas del archivo. Así es como normalmente se almacena el código Python, y la extensión de estos archivos es .py.

Así que, creemos un archivo .py. Para hacerlo, usa el Launcher de JupyterLab para abrir un editor de texto. Una vez abierto, puedes hacer clic derecho en la pestaña de la ventana del editor de texto para cambiar el nombre. Llamaremos a este archivo zen.py. Dentro de este archivo, ingresa las cuatro líneas de código que escribiste antes en la consola. Asegúrate de guardarlo.

Para ejecutar el código de este archivo, puedes invocar el intérprete de Python en la línea de comandos, seguido del nombre del archivo. Es decir, escribe

python zen.py

en la línea de comandos. Nota que cuando ejecutas código de esta manera, el intérprete termina después de ejecutar el código y no obtienes un prompt.

Para ejecutar el código de este archivo usando la consola de Jupyter, puedes usar la función mágica %run.

%run zen.py

Para cerrar la consola, puedes hacer clic en la pestaña Running a la izquierda de la ventana de JupyterLab y hacer clic en SHUTDOWN junto a la consola.

2.4. Jupyter

Hasta este punto, hemos presentado JupyterLab, su editor de texto y la consola, así como el propio intérprete de Python. Quizás te estés preguntando…

2.4.1. ¿Qué es Jupyter?

De la página oficial de Project Jupyter: >Project Jupyter es un proyecto de código abierto que nació del Proyecto IPython en 2014, evolucionando para soportar la ciencia de datos interactiva y la computación científica en todos los lenguajes de programación.

Así que, Jupyter es una extensión de IPython que lleva la computación interactiva más allá. Es independiente del lenguaje, como sugiere su nombre. El nombre «Jupyter» es una combinación de Julia (un lenguaje excelente y reciente para computación científica), Python (que ya conoces y amas), y R (la herramienta dominante para computación estadística). Sin embargo, puedes ejecutar más de 40 lenguajes diferentes en JupyterLab, no solo Julia, Python y R.

Centrales en Jupyter/JupyterLab son los notebooks de Jupyter. De hecho, el documento que estás leyendo ahora fue generado desde un notebook de Jupyter. Usaremos notebooks de Jupyter extensamente en el curso, junto con archivos .py.

2.4.2. ¿Por qué notebooks de Jupyter?

Cuando escribas código que reutilizarás, deberías desarrollar módulos completamente probados usando archivos .py. Siempre puedes importar esos módulos cuando uses un notebook de Jupyter. Así que, un notebook de Jupyter no es bueno para aplicaciones donde construyes código o scripts reutilizables. Sin embargo, los notebooks de Jupyter son muy útiles en las siguientes aplicaciones.

  1. Exploración de datos/análisis. Los notebooks de Jupyter son excelentes para probar cosas con código o explorar un conjunto de datos. Esto es una parte importante del proceso de investigación. El formato de los notebooks es ideal para organizar tus ideas mientras las sintetizas.

  2. Desarrollo de pipelines de procesamiento de imágenes. Esto es realmente un caso especial del punto anterior, pero vale la pena mencionarlo porque los notebooks de Jupyter son especialmente útiles para descubrir qué pasos son mejores para extraer datos útiles de imágenes, algo muy común en biología. Usando el notebook, puedes escribir lo que esperas lograr en cada paso y mostrar gráficamente los resultados como imágenes a medida que avanzas.

  3. Compartir tu razonamiento en el análisis. Como puedes combinar texto bien formateado y código ejecutable, los notebooks de Jupyter son ideales para compartir cómo realizas tus cálculos con colaboradores y lectores de tus publicaciones. Famosamente, LIGO usó un notebook de Jupyter para explicar el procesamiento de señales en su primer descubrimiento de una onda gravitacional.

  4. Pedagogía. Todo el contenido de esta clase, incluida esta lección, fue desarrollado usando notebooks de Jupyter.

Ahora que sabemos qué son los notebooks de Jupyter y la motivación para usarlos, ¡comencemos!

2.4.3. Iniciar un notebook de Jupyter

Para iniciar un notebook de Jupyter, haz clic en el ícono Notebook del Launcher de JupyterLab. Si quieres abrir un notebook existente, haz clic en él en la pestaña Files de la ventana de JupyterLab y ábrelo.

2.4.4. Celdas

Un notebook de Jupyter consiste en celdas. Los dos tipos principales de celdas que usarás son celdas de código y celdas de markdown, y profundizaremos en sus propiedades en breve. Primero, una visión general.

Una celda de código contiene código real que quieres ejecutar. Puedes especificar una celda como celda de código usando el menú desplegable en la barra de herramientas de tu notebook. También puedes presionar esc y luego y (denotado como «esc, y») mientras una celda está seleccionada para especificar que es una celda de código. Debes presionar enter después de hacer esto para comenzar a editarla.

Si quieres ejecutar el código en una celda de código, presiona «shift + enter». Nota que las celdas de código se ejecutan en el orden en que presionas «shift + enter». Es decir, el orden de las celdas que ejecutas es el orden en que el código se ejecuta. Si no ejecutaste explícitamente una celda al principio del documento, sus resultados no son conocidos por el intérprete de Python. Este es un punto muy importante y a menudo es fuente de confusión y frustración para los estudiantes.

Las celdas de markdown contienen texto. El texto se escribe en markdown, un lenguaje de marcado ligero. Puedes leer sobre su sintaxis aquí. También puedes insertar HTML en las celdas de markdown, y esto se mostrará correctamente. Mientras escribes el contenido de estas celdas, los resultados aparecen como texto. Al presionar «shift + enter» el texto se muestra con el formato que especificaste.

Puedes especificar una celda como celda de markdown en la barra de herramientas de Jupyter, o presionando «esc, m» en la celda. Nuevamente, debes presionar enter después de usar las teclas rápidas para entrar en modo de edición.

En general, cuando quieras agregar una nueva celda, puedes hacer clic en el ícono + en la barra de herramientas del notebook. El atajo para insertar una celda debajo es «esc, b» y para insertar una celda arriba es «esc, a». Alternativamente, puedes ejecutar una celda y agregar automáticamente una nueva debajo presionando «alt + enter».

2.4.5. Celdas de código

A continuación se muestra un ejemplo de una celda de código que imprime hola, mundo. Observa que la salida de la instrucción print aparece en la misma celda, aunque separada del bloque de código.

[ ]:
# Saluda al mundo.
print('Hola, mundo.')

Si evalúas una expresión de Python que devuelve un valor, ese valor se muestra como salida de la celda de código. Sin embargo, esto solo ocurre para la última línea de la celda de código.

[ ]:
# Mostrará 9 si esta fuera la última línea, pero no lo es, así que no muestra nada
4 + 5

# Espero que veamos 11.
5 + 6

Nota que si la última línea no devuelve un valor, como si asignamos una variable, no hay salida visible de la celda de código.

[ ]:
# Asignación de variable, así que no hay salida visible.
a = 5 + 6
[ ]:
# Sin embargo, ahora si pedimos a, su valor se mostrará
a

2.4.6. Visualización de gráficos

Usaremos Bokeh para comprobar que tu computador esta listo para trabajar, a pesar que utilizaremos exclusivamente Plotly durante el curso. Para asegurarte de que los gráficos de Bokeh se muestren en el notebook, debes ejecutar

bokeh.io.output_notebook()

en tu notebook. Es buena práctica ejecutar esto en la primera celda del notebook. Ahora hagamos un gráfico usando Bokeh.

[ ]:
# Generar datos para graficar
x = np.linspace(0, 2 * np.pi, 200)
y = np.exp(np.sin(np.sin(x)))

# Configurar gráfico
p = bokeh.plotting.figure(
    frame_height=200,
    frame_width=250,
    x_axis_label='x',
    y_axis_label='y',
    x_range=[0, 2 * np.pi],
)

# Dibujar línea
p.line(x, y, line_width=2)

bokeh.io.show(p)

2.4.7. Formato adecuado de las celdas

En general, es buena idea mantener las celdas simples. Puedes definir una función, o tal vez dos o tres funciones estrechamente relacionadas, en una sola celda, y eso es suficiente. Cuando definas una función, asegúrate de que esté debidamente comentada con un docstring descriptivo. A continuación se muestra un ejemplo de cómo podría generar un gráfico del atractor de Lorenz (que elijo solo porque es divertido) con celdas de código y celdas de markdown explicando lo que hago. (El docstring en esta función es extenso, pero para las tareas basta con algo similar a la primera línea del docstring.)

Entre celdas, deberías explicar con texto lo que estás haciendo. Veamos un ejemplo divertido.

Usaremos scipy.integrate.odeint() para integrar numéricamente el atractor de Lorenz. Por lo tanto, primero definimos una función que devuelve el lado derecho del sistema de EDOs que define el atractor de Lorenz.

[ ]:
def atractor_lorenz(r, t, p):
    """
    Calcula el lado derecho del sistema de EDOs para el atractor de Lorenz.

    Parámetros
    ----------
    r : array_like, shape (3,)
        Posición (x, y, z) de la trayectoria.
    t : argumento_dummy
        Argumento dummy, necesario para pasar la función a
        scipy.integrate.odeint
    p : array_like, shape (3,)
        Parámetros (s, k, b) para el atractor.

    Retorna
    -------
    output : ndarray, shape (3,)
        Derivadas temporales del atractor de Lorenz.

    Notas
    -----
    .. Retorna el lado derecho del sistema de EDOs que describe
       el atractor de Lorenz.
        x' = s * (y - x)
        y' = x * (k - z) - y
        z' = x * y - b * z
    """
    # Desempaquetar variables y parámetros
    x, y, z = r
    s, p, b = p

    return np.array([s * (y - x),
                     x * (p - z) - y,
                     x * y - b * z])

Con esta función, solo tenemos que elegir nuestras condiciones iniciales y puntos de tiempo y ejecutar la integración numérica.

[ ]:
# Parámetros a usar
p = np.array([10.0, 28.0, 8.0 / 3.0])

# Condición inicial
r0 = np.array([0.1, 0.0, 0.0])

# Puntos de tiempo a muestrear
t = np.linspace(0.0, 30.0, 4000)

# Usar scipy.integrate.odeint para integrar el atractor de Lorenz
r = scipy.integrate.odeint(atractor_lorenz, r0, t, args=(p,))

# Desempaquetar resultados en x, y, z.
x, y, z = r.transpose()

Ahora, construiremos un gráfico de la trayectoria usando Bokeh.

[ ]:
# Configurar gráfico
p = bokeh.plotting.figure(
    frame_height=200,
    frame_width=200,
    x_axis_label='x',
    y_axis_label='z',
)

# Dibujar línea
p.line(x, z)

bokeh.io.show(p)

2.4.8. Buenas prácticas para celdas de código

Aquí tienes un resumen de algunas reglas generales para componer y formatear tus celdas de código.

  1. Mantén el ancho del código en las celdas por debajo de 80 caracteres. No es un límite estricto, pero deberías intentarlo y considerar 88 caracteres como un límite duro.

  2. Mantén tus celdas de código cortas. Si tienes una celda de código muy grande, divídela.

  3. Proporciona docstrings completos para cualquier función que definas. Puedes y debes tener comentarios en tu código, pero realmente no deberías necesitar muchos porque tus celdas de markdown alrededor del código deberían describir claramente lo que intentas hacer.

  4. Haz todos tus imports en la primera celda de código al principio del notebook. Excepto por los imports del tipo «from ... import ...», importa un módulo por línea. También debes incluir bokeh.io.output_notebook() en la celda superior cuando uses Bokeh.

  5. Para entregar tareas, siempre muestra tus gráficos en el notebook.

2.4.9. Celdas de markdown

Las celdas de markdown contienen texto. El texto se escribe en markdown, un lenguaje de marcado ligero. La lista de construcciones sintácticas en este enlace es prácticamente todo lo que necesitas saber para markdown estándar. También puedes insertar HTML en las celdas de markdown, y esto se mostrará correctamente. Mientras escribes el contenido de estas celdas, los resultados aparecen como texto. Al presionar «shift + enter» el texto se muestra con el formato que especificaste.

Puedes especificar una celda como celda de markdown en la barra de herramientas de Jupyter, o presionando «esc, m» en la celda. Nuevamente, debes presionar enter después de usar las teclas rápidas para entrar en modo de edición.

Además de HTML, puedes insertar algunas expresiones \(\LaTeX\) en las celdas de markdown. \(\LaTeX\) (pronunciado «lay-tech») es un lenguaje de marcado de documentos que usa el software de tipografía \(\TeX\). Es especialmente adecuado para la tipografía de expresiones matemáticas. En los notebooks de Jupyter, la entrada matemática de \(\LaTeX\) se muestra usando MathJax. Esto normalmente se ejecuta desde un servidor remoto, así que si no tienes conexión a internet, tus ecuaciones pueden no mostrarse. Usarás \(\LaTeX\) extensamente en la preparación de tus tareas. Hay muchos recursos en internet para comenzar con \(\LaTeX\), pero solo necesitarás una pequeña parte de su funcionalidad en tus tareas, y la siguiente parte de esta lección, además de hojas de referencia que puedes encontrar en Google (como esta), son útiles.

2.4.10. Atajos de teclado

Hay algunos atajos de teclado que son convenientes de usar en JupyterLab. (No todos funcionan en Colab.) Ya vimos Shift + Enter para ejecutar una celda de código. Importante: presionar Esc te lleva al modo comando, en el que no editas el contenido de una celda, sino que haces cosas como agregar celdas. A continuación algunos atajos útiles. Si dos teclas están separadas por un signo +, se presionan simultáneamente, y si están separadas por un -, se presionan en sucesión.

Atajo

modo

acción

Esc - m

comando

cambiar celda a markdown

Esc - y

comando

cambiar celda a código

Esc - a

comando

insertar celda arriba

Esc - b

comando

insertar celda abajo

Esc - d - d

comando

borrar celda

Alt + Enter

edición

ejecutar celda e insertar una debajo

Hay muchos otros (y se muestran en los menús desplegables dentro de JupyterLab), pero estos son los que más uso.

2.5. Renderizado de notebooks como HTML

Cuando entregues tareas, también deberás entregar una versión HTML de tus notebooks. Para guardar un notebook como HTML, haz clic en File → Export Notebook As... → Export Notebook to HTML.