{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Introducción a Python para ciencias e ingenierías (notebook 5)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ing. Martín Gaitán\n", "\n", "Twitter: `@tin_nqn_`\n", "\n", "Email: `gaitan@gmail.com`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "**Links útiles**" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Repositorio del curso:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### http://bit.ly/cursopy" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Python \"temporal\" online:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### http://try.jupyter.org" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- Descarga de [Python \"Anaconda\"](http://continuum.io/downloads#py34)\n", "- Resumen de [sintaxis markdown](https://github.com/jupyter/strata-sv-2015-tutorial/blob/master/resources/Working%20With%20Markdown%20Cells.ipynb)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "- python.org.ar (Python General -- Tod@s!)\n", "- scipyla.org (Python Científico - en portuñol/ingles)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "--------" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Una yapa de Numpy: Vectorizar funciones " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "\n", "Sabemos que Numpy opera vectorialmente, es decir, ejecutando la operación aritmetica o la \"función universal\" (ufunc)\n", "a cada uno de los elementos de los operadores." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "import numpy as np\n", "x = np.array([1, 2., 3.])\n", "y = np.array([.3, -5, 10])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También sabemos que cuando operamos un vector con un escalar se aplica el broadcasting" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x >= 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "pero no podemos hacer un \"casting\" automático de un array tipo booleano a un sólo booleano" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "bool(x >= 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ese \"cast\" se puede hacer con funciones de agregación booleanas, como `all`, `allclose`, `any`, etc. pero muchas veces eso implica cambiar código que ya tenemos escrito" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "np.all(x >= 2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por ejemolo, veamos este par de funciones" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def func1(a):\n", " return a ** 2\n", "\n", "\n", "def func2(a):\n", " \"\"\"Return the same value if it's negative, otherwise returns its square\"\"\"\n", " \n", " if a < 0:\n", " return a\n", " else:\n", " return a**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "obviamente ambas funcionan con escalares," ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "func1(10), func2(-4)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Y `func1` funciona también para arrays, debido a que la operación que hace (potencia) admite broadcasting." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "func1(np.arange(10))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sin embargo, como el casting de un array de booleanos a un sólo booleano no es automático, `func2` no es \"universal\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "func2(np.arange(10))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lo que necesitamos es **vectorizar la función**. `vectorize` transforma una función cualquiera en una de tipo universal: esto es, cuando un parámetro es un array y la aplicación directa no funciona, automáticamente se realiza una iteración implicita elemento a elemento." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "v_func2 = np.vectorize(func2)\n", "v_func2(np.arange(10)) # para cada elemento de x, aplica func2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "type(v_func2), v_func2.__doc__" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Y sigue funcionando para escalares" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "v_func2(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicio" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Defina como función universal de numpy la siguiente función definida por partes y grafique entre -5 y -5" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$$\n", " y = f(x) =\n", " \\left \\{\n", " \\begin{array}{rcl}\n", " x + 3, & \\mbox{si } & x < -1 \\\\\n", " x^2+1, & \\mbox{si } & -1 \\le x \\le 2 \\\\\n", " 5, & \\mbox{si } & x > 2\n", " \\end{array}\n", " \\right .\n", "$$\n", "\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Scipy: parado sobre hombros de gigantes" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La biblioteca Scipy se basa en los arrays multidimensionales de Numpy e implementa cientos de algoritmos científicos de alto nivel, clasificados en subpaquetes temáticos." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "* Integración y ecuaciones diferenciales ([scipy.integrate](http://docs.scipy.org/doc/scipy/reference/integrate.html))\n", "* Optimización ([scipy.optimize](http://docs.scipy.org/doc/scipy/reference/optimize.html))\n", "* Interpolación ([scipy.interpolate](http://docs.scipy.org/doc/scipy/reference/interpolate.html))\n", "* Transformada de Fourier ([scipy.fftpack](http://docs.scipy.org/doc/scipy/reference/fftpack.html))\n", "* Procesamiento de señales ([scipy.signal](http://docs.scipy.org/doc/scipy/reference/signal.html))\n", "* Álgebra lineal (mejor que `numpy.linalg`) ([scipy.linalg](http://docs.scipy.org/doc/scipy/reference/linalg.html))\n", "* Algoritmos optimizados para matrices ralas ([scipy.sparse](http://docs.scipy.org/doc/scipy/reference/sparse.html))\n", "* Estadística ([scipy.stats](http://docs.scipy.org/doc/scipy/reference/stats.html))\n", "* Procesamiento de imágenes ([scipy.ndimage](http://docs.scipy.org/doc/scipy/reference/ndimage.html))\n", "* Entrada/salida de archivos ([scipy.io](http://docs.scipy.org/doc/scipy/reference/io.html))\n", "* Funciones especiales ([scipy.special](http://docs.scipy.org/doc/scipy/reference/special.html))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "y hay más! Toda la documentación en http://docs.scipy.org/doc/scipy/reference/" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Veamos algunas aplicaciones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "\n", "## Integrales" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La evaluación numérica de integrales de la forma" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "$\\displaystyle \\int_a^b f(x) dx$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "se llaman *cuadratura numérica*, o simplemente *cuadratura*. SciPy tiene las funciones `quad`, `dblquad` y `tplquad` para cuadraturas simples, dobles o triples." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "quad" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy.integrate import quad\n", "\n", "# definimos f f(x)\n", "def f(x):\n", " return 2*x" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "val, abserr = quad(f, 0, 3)\n", "print(\"integral value =\", val, \", absolute error =\", abserr)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ya que estamos definiendo \"funciones objetivo\", hay otra manera de definir funciones simples en python, que sólo si queremos las asignamos a un nombre. \n", "Por ejemplo \n", "\n", "```python\n", "def f(x): \n", " return x+2\n", "```\n", "\n", "se podría definir así" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# otro ejemplo de funcion lambda\n", "f = lambda x: x+2 # -> def f(x): return x**2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "f(2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Lo útil es que esta forma de crear **funciones anónimas** permite definirlas directamente al pasarla como argumento" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "quad(lambda x: x**2, 0, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Integración de funciones con parámetros adicionales\n", "\n", "\n", "Si necesitaramos pasarle parámetros a nuestra función lo hacemos en un tupla en el argumento `args`. Por ejemplo, supongamos que tenemos una función de la forma $g(x) = x^n$ donde `x` es la variable independiente y `n` es un parámetro." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def g(x, n):\n", " return x**n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si quisieramos evaluar la integral de esta función de x fijando n en 3" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# evalua la integral x**3\n", "quad(g, 0, 5, args=(3,))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from scipy import integrate" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate.dblquad" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ecuaciones diferenciales ordinarias\n", "\n", "El paquete de integración también tiene funciones para resolver [ecuaciones diferenciales ordinarias](https://en.wikipedia.org/wiki/Ordinary_differential_equation)." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por ejemplo, para resolver \n", "\n", "$$\\frac{\\mathrm{d}y}{\\mathrm{d}t} = -2y$$\n", "\n", " con $t \\in [-1, 5]$ y la condición inicial $y(0) = 1$ " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline \n", "\n", "from matplotlib import pyplot as plt\n", "import numpy as np\n", "\n", "from scipy.integrate import odeint\n", "\n", "t = np.linspace(-1, 5, 100)\n", "y = odeint(lambda y,t: -2*y, 1, t)\n", "plt.plot(t,y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Como vemos, [el resultado es correcto](http://www.wolframalpha.com/input/?i=y%27+%3D+-2y)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ejercicios\n", "\n", "1. Dado el ejemplo de [gráfico \"fill\"](http://matplotlib.org/examples/lines_bars_and_markers/fill_demo.html) calcular el área de toda la superficie sombreada en rojo\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x = np.linspace(0, 1, 1000)\n", "y = np.sin(4 * np.pi * x) * np.exp(-5 * x)\n", "plt.fill(x, y, 'r')\n", "plt.grid(True)\n", "plt.show()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# %load https://gist.githubusercontent.com/mgaitan/36d4dbce14ab4dc69f52/raw/9d040d916ebb77bf7ff2618a59e9b6ad95db71e8/area.py\n", "# primero hay que observar que al pedir \"area\" se interpreta que la parte negativa de la curva aporta área \n", "\n", "plt.fill(x, np.abs(y))\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "\n", "# luego, mediante integracion numerica de la función absoluta\n", "quad(lambda x: np.abs(np.sin(4 * np.pi * x) * np.exp(-5 * x)), 0, 1)[0]\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "\n", "# otra manera: directamente aplicar el método de trapezoides (teniendo datos y no la funcion)\n", "np.trapz(np.abs(y), x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Optimización y ajuste de curvas\n", "\n", "### encontrar mínimos\n", "\n", "Supongamos que tenemos una función cualquiera de una o más variables\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "def fpol(x):\n", " return x**4 + 5*x**3 + (x-2)**2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "fig, ax = plt.subplots()\n", "x = np.linspace(-5, 2, 100)\n", "ax.plot(x, fpol(x));" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos encontrar un mínimo local con la función `minimize`, que recibe como parámetro la función objetivo y un *valor de estimación inicial* a partir del cual se comienza a \"ajustar\"" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy import optimize\n", "result = optimize.minimize(fpol, -3, method='BFGS') # http://en.wikipedia.org/wiki/BFGS\n", "result" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "result['x']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "`minimize` es una \"función paraguas\" para diferentes algoritmos, que se pueden elegir mediante el parámetro `method` o bien utilizar la función explícita de minimización que lo implementa.\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "optimize.minimize(fpol, 0, method='hBFGS')['x']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Ojo que hay métodos que son muy sensibles al valor de estimación" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "optimize.minimize(fpol, 0, method='Powell')['x']" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ejercicio \n", "\n", "1. Encuentre el mínimo y el máximo de la función \n", "\n", "$$f(x,y) = xe^{-x^2 - y^2}$$\n", "\n", "2- Basado en los ejemplos de gráficos de [superficie](http://matplotlib.org/examples/mplot3d/surface3d_demo.html), y [scatter 3d](http://matplotlib.org/examples/mplot3d/scatter3d_demo.html) grafique la superficie para $x, y \\in [(-2, 2),(-2,2)]$ con un punto triangular en los puntos encontrados anteriormente\n", "\n", "" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# %load https://gist.githubusercontent.com/mgaitan/faa930a5874311a6f888/raw/ec7ff8268935ab53095c3067c12210d26c40b406/min_and_max.py\n", "%matplotlib inline\n", "\n", "import numpy as np\n", "from matplotlib import pyplot as plt\n", "from mpl_toolkits.mplot3d import Axes3D\n", "from matplotlib import cm\n", "\n", "x = y = np.linspace(2, -2, 100)\n", "xx,yy = np.meshgrid(x, y)\n", "\n", "f = lambda var: var[0]*np.exp(-var[1]**2 - var[0]**2)\n", "\n", "z = f([xx,yy])\n", "\n", "fig = plt.figure()\n", "fig.set_size_inches(10,10)\n", "ax = fig.gca(projection='3d')\n", "ax.plot_surface(xx,yy,z, rstride=1, cstride=1, cmap=cm.coolwarm,\n", " linewidth=0)\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "\n", "# ----\n", "from scipy import optimize\n", "minimum = optimize.minimize(f, [-1, 1])\n", "maximum = optimize.minimize(lambda x: -f(x), [1, 1])\n", "minimum, maximum\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "\n", "# ----\n", "\n", "ax.scatter(minimum['x'][0], minimum['x'][1], minimum['fun'], marker='v', s=200)\n", "ax.scatter(maximum['x'][0], maximum['x'][1], f(maximum['x']), marker='^', s=200)\n", "fig\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Curve fitting\n", "\n", "\n", "Otra tarea frecuente es ajustar parámetros de una función objetivo a partir de un *dataset* de puntos conocidos. \n", "\n", "Supongamos que tenemos una serie de datos medidos\n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "dataset = np.array([[ 0. , 3.07127661],\n", " [ 0.08163265, 2.55730445],\n", " [ 0.16326531, 2.28438915],\n", " [ 0.24489796, 1.91475822],\n", " [ 0.32653061, 2.00380351],\n", " [ 0.40816327, 1.89419135],\n", " [ 0.48979592, 1.74713349],\n", " [ 0.57142857, 1.68237822],\n", " [ 0.65306122, 1.44749977],\n", " [ 0.73469388, 1.67511522],\n", " [ 0.81632653, 1.34023054],\n", " [ 0.89795918, 1.1209472 ],\n", " [ 0.97959184, 1.41692478],\n", " [ 1.06122449, 0.88480583],\n", " [ 1.14285714, 0.9939094 ],\n", " [ 1.2244898 , 1.02293629],\n", " [ 1.30612245, 1.11983417],\n", " [ 1.3877551 , 0.77520734],\n", " [ 1.46938776, 0.88371884],\n", " [ 1.55102041, 1.24492445],\n", " [ 1.63265306, 0.8275613 ],\n", " [ 1.71428571, 0.60846983],\n", " [ 1.79591837, 0.73019407],\n", " [ 1.87755102, 0.75139707],\n", " [ 1.95918367, 0.6496137 ],\n", " [ 2.04081633, 0.59122461],\n", " [ 2.12244898, 0.61734269],\n", " [ 2.20408163, 0.61890166],\n", " [ 2.28571429, 0.68647436],\n", " [ 2.36734694, 0.47551378],\n", " [ 2.44897959, 0.89850013],\n", " [ 2.53061224, 0.53029377],\n", " [ 2.6122449 , 0.74853936],\n", " [ 2.69387755, 0.371923 ],\n", " [ 2.7755102 , 0.43536233],\n", " [ 2.85714286, 0.40515777],\n", " [ 2.93877551, 0.52171142],\n", " [ 3.02040816, 0.53069869],\n", " [ 3.10204082, 0.71363042],\n", " [ 3.18367347, 0.54962316],\n", " [ 3.26530612, 0.7133841 ],\n", " [ 3.34693878, 0.27204244],\n", " [ 3.42857143, 0.56572211],\n", " [ 3.51020408, 0.29310287],\n", " [ 3.59183673, 0.50044492],\n", " [ 3.67346939, 0.60938301],\n", " [ 3.75510204, 0.55696286],\n", " [ 3.83673469, 0.59409416],\n", " [ 3.91836735, 0.30335525],\n", " [ 4. , 0.24230362]]\n", " )" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x, y = dataset[:,0], dataset[:,1]\n", "\n", "fig = plt.figure(figsize=(9,6))\n", "ax = fig.add_subplot(1, 1, 1)\n", "ax.scatter(dataset[:,0], dataset[:,1], marker='^');" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Vemos que tiene forma de exponencial decreciente, es decir\n", "\n", "$$\n", " f(x) = ae^{-bx} + c\n", "$$\n", "\n", "El objetivo es encontrar cuales son los valores de los parámetros `a`, `b` y `c` que mejor ajustan la curva a los puntos dados. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "def func(x, a, b, c): # x es la variable independiente, a b y c los parametros a encontrar\n", " return a*np.exp(-b*x) + c\n", "\n", "\n", "popt, pcov = optimize.curve_fit(func, x, y)\n", "popt" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por lo tanto la curva que mejor ajusta a nuestros datos es\n", "\n", "$$f(x) = 2.33e^{-1.18x} + 0.25$$" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "ax.plot(x, func(x, *popt), 'r', label='fitted')\n", "fig" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Procesamiento de imágenes\n", "\n", "Una imágen digital tipo [raster](https://en.wikipedia.org/wiki/Raster_graphics) (matriz de pixeles) puede ser facilmente interpretable como un array multidimensional. Por ejemplo, una imágen de 512x512 pixeles a color puede alamcenarse en una \"matriz\" de 3x512x512 donde cada una las 3 matrices representa una capa de colo RGB (rojo, verde, azul)\n", "\n", "Para una imágen monocromática, obviamente una sóla matriz nos alcanza. \n", "\n", "Scipy trae el array de una [imágen clásica](https://en.wikipedia.org/wiki/Lenna) (fragmento de una foto de PlayBoy de 1972) para ejemplos de procesamiento de imágenes, en escala de grises. \n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy.misc import lena\n", "image = lena()\n", "image.shape," ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%matplotlib inline\n", "from matplotlib import pyplot as plt\n", "plt.gray()\n", "plt.imshow(image)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos procesar imágenes simplemente aplicando máscaras \n", "\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "mascara = (image > image.max() * .75)\n", "plt.imshow(mascara) # blanco == True" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos aplicar la máscara a la imágen original, por ejemplo, " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "plt.imshow(np.where(mascara, image, 255))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "mask = np.tril(np.ones(image.shape)) #tril / triu seleccionan triangulos inf y sup\n", "plt.imshow(np.where(mask, image, 255))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Scipy trae un paquete para manipulación de **imágenes multidimensionales** " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "from scipy import ndimage" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "plt.imshow(ndimage.convolve(image, np.ones((12,12))))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Transformaciones" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "lena = image\n", "shifted_lena = ndimage.shift(lena, (50, 50))\n", "shifted_lena2 = ndimage.shift(lena, (50, 50), mode='nearest')\n", "rotated_lena = ndimage.rotate(lena, 30)\n", "cropped_lena = lena[50:-50, 50:-50]\n", "zoomed_lena = ndimage.zoom(lena, 5)\n", "imgs = (shifted_lena, shifted_lena2, rotated_lena, cropped_lena, zoomed_lena)\n", "fig, axes = plt.subplots(1, 5, figsize=(20,100))\n", "for ax, img in zip(axes, imgs):\n", " ax.tick_params(left=False, bottom=False, labelleft=False)\n", " ax.imshow(img)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Filtros" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from scipy import signal\n", "\n", "noisy_lena = np.copy(lena).astype(np.float)\n", "noisy_lena += lena.std()*0.5*np.random.standard_normal(lena.shape)\n", "blurred_lena = ndimage.gaussian_filter(noisy_lena, sigma=3)\n", "median_lena = ndimage.median_filter(blurred_lena, size=5)\n", "wiener_lena = signal.wiener(blurred_lena, (5,5))\n", "imgs = (noisy_lena, blurred_lena, median_lena, wiener_lena)\n", "fig, axes = plt.subplots(1, 4, figsize=(20,80))\n", "for ax, img in zip(axes, imgs):\n", " ax.tick_params(left=False, bottom=False, labelleft=False)\n", " ax.imshow(img)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si les interesa esta área deberian ver los paquetes especializados [Scikit-image](http://scikit-image.org/), [Pillow](http://pillow.readthedocs.org) y [OpenCV](http://opencv.org/)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# A now, something completely different: SymPy!\n", "\n", "([intertextualidad :D](https://en.wikipedia.org/wiki/And_Now_for_Something_Completely_Different)) De paso, sabías que el Python se llama así porque el holandés que lo creo es fanático de Monty Python)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy es una biblioteca Python para matemática simbólica, similar a software como Mathematica o Mathcad. La documentación se encuentra en http://sympy.org/ ." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "En Anaconda (full) ya viene instalado, o se puede instalar via pip o conda con" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " $ pip install sympy " ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### ¿que es la computación simbólica?" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Comunmente, las computadoras usan una [coma flotante](http://en.wikipedia.org/wiki/Floating_point) para **representar** numeros reales (y complejos) y calcular operaciones matemáticas. Esto implica que la precisión es limitada" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import math\n", "math.sqrt(8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Los sistemas de cálculo simbólico (o álgebra computacional, CAS), utilizan una **representación simbólica** (presentada de la manera más simplicifada posible)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import sympy\n", "\n", "raiz8 = sympy.sqrt(8)\n", "raiz8" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Podemos, por supuesto, **evaluar** la expresión simbólica" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "raiz8.evalf()" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "raiz8.evalf(n=150)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por defecto la evaluación numérica se lleva a cabo con un precisión de 15 decimales.\n", "Pero puede ajustarse la precisión al número de decimales que uno desee, enviando el número de decimales como argumento a evalf() o a la función `N()`" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy utiliza como background la biblioteca [mpmath](http://code.google.com/p/mpmath/) que le permite realizar cálculos con aritmética de **precisión arbitraria**, de forma tal que ciertas constantes especiales, como pi, el número e, oo (infinito), son tratadas como símbolos y pueden ser evaluadas con aritmética de alta precisión:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Salida enriquecida" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Para continuar, haremos que el \"output matemático\" se vea más bonito" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "import sympy\n", "from sympy.interactive import printing\n", "printing.init_printing(use_latex='mathjax')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Esa función inicializa el output en le mejor modo disponible en el entorno. Como los notebooks saben mostrar LaTex, lo hará así, mostrando *outputs* muy bonitos." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.sqrt(8)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### SymPy como una calculadora" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy tiene tres tipos de datos predefinidos: el real (Real), el racional (Rational) y el entero (Integer).\n", "El tipo `Rational` representa a un número racional como un par de números enteros: el numerador y el denominador.\n", "Por ejemplo: `Rational(1, 2)` representa la fracción $1/2$, `Rational(5, 3)` a $5/3$, etc." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = sympy.Rational(1, 2)\n", "a" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a*2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.pi**2" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.pi.evalf(n=200)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "(sympy.pi+sympy.exp(1)).evalf()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También existe una clase para representar al infinito matemático, llamada oo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.oo > 99999" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.oo + 1" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "1 / sympy.oo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "otra manera de ejecutar `evalf` de una expresión es con la función `sympy.N`" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.N(sympy.sqrt(2), 100)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ejercicios:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Calcular 1/2 + 1/3 con aritmética racional.\n", "2. Calcular $2^e$ con 200 decimales" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Símbolos" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "El alma del Cálculo Simbólico son, naturalmente, las variables simbólicas, que en SymPy son instancias de la clase `Symbol`. Una explicación intuitiva es que, mientras que las variables ordinarias tienen un valor que puede ser un número, una cadena, un valor verdadero / falso, una secuencia, etc. las variables simbólicas juegan el papel de \"contenedores\": no sabemos a priori lo que pueden ser" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x = sympy.Symbol('x')\n", "y = sympy.Symbol('y')\n", "n = sympy.Symbol('n', integer=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Luego, pueden ser manipuladas:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x + y + x - y" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "(x + y)**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Una manera más compacta de definir variables simbólicas es con la función `symbols`, que permite pasar una cadena con muchas variables a generar separadas por espacios." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a, b = sympy.symbols('a b')\n", "(a - b)**2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Traducir expresiones a otros lenguajes\n", "\n", "Podemos aprovechar toda la funcionalidad de \"impresión\" que trae Sympy para traducir cualquier expresión a otros formatos. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy import sin, exp, cos\n", "\n", "formula = sin(x)*exp(cos(x)**x)/x\n", "print(sympy.latex(formula, mode='equation', itex=True))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Sólo nos queda copiar y pegar esa expresión en markdown\n", "\n", "$$\\frac{1}{x} e^{\\cos^{x}{\\left (x \\right )}} \\sin{\\left (x \\right )}$$\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.ccode(formula) # codigo C ansi" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.fcode(formula) # codigo fortran iso" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Manipulación algebráica" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy tiene una gran potencia para realizar cálculos en forma algebráica." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.expand((x+y)**2, deep=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "también se pueden hacer especificaciones adicionales:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.expand(x + y, complex= True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "A veces es útil darle \"pistas\" al sistema para que sepa por qué \"camino matemático\" andar" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.expand(sympy.cos(x + y))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.expand(sympy.cos(x + y), trig=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Simplificación" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.simplify(x**2 + 2*x*y + y**2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "La simplificación se realiza de la mejor manera que SymPy encuentra y a veces la respuesta puede no ser lo que uno espera (demasiado trivial o no en la forma que se necesita). Las pistas la estrategia de simplificación que debe utilizar:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "* powsimp: simplifica exponentes.\n", "* trigsimp: simplifica expresiones trigonométricas\n", "* logcombine\n", "* randsimp\n", "* together" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ejercicios:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Calcular la forma expandida de $(x+y)^6.$\n", "2. Simplificar la expresión trigonométrica $\\frac{sen(x)}{cos(x)}$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Límites" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Los límites se pueden calcular con mucha facilidad usando SymPy.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ " limit(f(x), x, 0)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy import limit, sin, oo\n", "limit(sin(x)/x, x, 0), limit(sin(x)/x, x, oo)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Diferenciación" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se puede derivar cualquier expresión de Sympy" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy import diff, tan, exp, cos, sin\n", "\n", "diff(sin(x), x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "diff(exp(sin(x**3)**x), x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Se pueden calcular derivadas de orden superior especificando el orden de derivación como tercer argumento de diff:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "diff(sin(2*x), x, 2)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "diff(sin(2*x), x, 3)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Expansión en serie de Taylor" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy puede expandir funciones en serie de Taylor mediante la función:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.series(sympy.cos(x), x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "#### Ejercicios:" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "1. Calcular el límite de $$\\lim_{x \\to 0} sen(x)\\frac{exp(cos(x)^x)}{x}$$\n", "2. Calcular las tres primeras derivadas de $$log{ (x^{2} - tan{(x)})}$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Integración" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy es capaz de calcular integrales definidas e indefinidas para funciones elementales, trascendentes y especiales, mediante la herramienta integrate()." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Integración de funciones elementales:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy import integrate, log\n", "integrate(6*x**5, x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate(sin(x), x)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy import sinh\n", "integrate(2*x + sinh(x), x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Integración de funciones especiales:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate(exp(-x**2)*sympy.erf(x), x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También es posible calcular integrales definidas. La función es la misma: `integrate(función, (varialble, límite inferior, límite superior))`, sólo que como segundo argumento se utiliza una tupla cuyo primer elemento es la variable de integración, su segundo elemento es el límtie inferior de integración y el último es el límite superior." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate(x**3, (x, -1, 1))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate(cos(x), (x, -sympy.pi/2, sympy.pi/2))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "¡Incluso se puden calcular integrales impropias!" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate(exp(-x), (x, 0, sympy.oo))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "integrate(exp(-x**2), (x, -sympy.oo, sympy.oo))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Resolución de ecuaciones" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "SymPy es capaz de resolver ecuaciones algebráicas de una y de varias variables. Para eso existe la función `solve(ecuación, variable)`, donde ecuación es una expresión que es igual a cero." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Por ejemplo, para resolver la ecuación $x^4−1=0$" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.solve(x**4 - 1, x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "También se pueden resolver sistemas de ecuaciones en varias variables. Ahora el primer argumento de solve es una lista cuyos elementos son las ecuaciones a resolver, y el segundo argumento es otra lista formada por las variables o incógnitas del sistema. Por ejemplo:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.solve([x + 5*y - 2, -3*x + 6*y - 15], [x, y])" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Puede resolver ecuaciones en las que intervengan funciones trascendentes, pero su capacidad es limitada y, a veces, no encuentra la solución." ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.solve(exp(x) + 1, x)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Factorizacion \n", "\n", "Es posible factorizar polinomios en términos de factores irreducibles con la función `factor(función)`:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy import factor\n", "f = x**4 - 3*x**2 + 1\n", "factor(f)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Ecuaciones diferenciales" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "x, g = sympy.symbols('x g')\n", "expresion = g(x).diff(x, x) + g(x)\n", "expresion" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "sympy.dsolve(expresion, g(x))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Si uno quiere la ecuación diferencial sea resuelta de un modo en particular, puede incluir \"pistas\" como segundo argumento de dsolve para guiarlo en la resolución:" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "expresion = sin(x)*cos(g(x)) + cos(x)*sin(g(x))*g(x).diff(x)\n", "sympy.dsolve(expresion, g(x), hint='separable')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Sympy, numpy y otras yerbas\n", "\n", "Sympy es capaz de evaluar numéricamente una expresión usando Numpy. Para esto se usa la función `lambdify` que sabe generar una función universal\n" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [ "expr = sin(x)/x\n", "f = sympy.lambdify(x, expr, \"numpy\")" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "a = np.linspace(0.0001, 10, 100)\n", "f(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Pero sympy va más lejos y sabe compilar una expresión, usando lenguajes como Fortran o Cython que son aún más rápidos que usar C. " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "from sympy.utilities.autowrap import ufuncify\n", "f2 = ufuncify([x], expr, backend='f2py')" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "f2(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "# para los incrédulos\n", "np.all(f(a) == f2(a))" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%timeit f(a)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "%timeit f2(a)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# C'est fini\n", "\n", "Pero hay mucho más en este curso para seguir por tu cuenta\n", "\n", "- Gráficos más lindos con Seaborn y análisis de datos con Pandas [Clase](/notebooks/Clase%208.ipynb)\n", "- Interactivad y contenidos enriquecidos en el notebook [Clase](/notebooks/Clase%207.ipynb)\n", "- Integrar Python con código Fortran (puaj!) [Clase]((/notebooks/Clase%205b.ipynb)\n", "- Acelerando Python con Cython y Numba [Clase](/notebooks/Clase%206.ipynb)\n", "- Cómo instalar otros paquetes y distribuir los tuyos [Clase](/notebooks/Clase%208.ipynb)\n", "\n", "\n", "Además, hay cientos de bibliotecas científicas para temáticas específicas, que en general se basan en Numpy/Scipy\n", "\n", "- Machine Learning: [Scikit-learn](http://scikit-learn.org/stable/)\n", "- Procesamiento de imágenes avanzado: [Scikit-Image](http://scikit-image.org/) y [OpenCV](http://docs.opencv.org/3.0-beta/doc/py_tutorials/py_tutorials.html)\n", "- Paralelización/GPU: [Theano](http://deeplearning.net/software/theano/)\n", "- Astronomía: [Astropy](http://www.astropy.org/)\n", "- Biología molecular: [Biopython](http://biopython.org/)\n", "- Química molecular: [Chemlab](http://chemlab.readthedocs.org/)\n", "- Y [decenas](https://scikits.appspot.com/scikits), qué digo, [cientos](http://www.scipy.org/topical-software.html), qué digo, [miles](https://pypi.python.org/pypi?%3Aaction=search&term=science&submit=search) paquetes más!\n", "\n", "\n", "## Tareas Importantes\n", "\n", "- Sumate a la comunidad de Python más copada del mundo\n", "\n", "
\n", "
\n", "

Suscribite a la lista Python Argentina

\n", "
\n", "
\n", "
\n", "
\n", " \n", "
\n", " \n", "
\n", "
\n", "
\n", " \n", "- Vení a la conferencia anual! es Gratis! " ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false, "scrolled": false }, "outputs": [], "source": [ "from IPython.display import IFrame\n", "IFrame(src='http://ar.pycon.org', height=510, width=\"100%\")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Y dame feedback (sincero) sobre el curso" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": false }, "outputs": [], "source": [ "IFrame(src=\"https://docs.google.com/forms/d/1e2zHvV6ae3bQAjLsZuyZ_C5AJ2PGDkdpUD2pBH3mMRE/viewform?embedded=true\", width=\"100%\", height=500)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "collapsed": true }, "outputs": [], "source": [] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.4.0" } }, "nbformat": 4, "nbformat_minor": 0 }