282
Universidad de Oviedo Grado en F´ ısica Curso 2014-15 Introducci´ on a la F´ ısica Computacional Tema 4 odulos para c´ alculo cient´ ıfico en Python

Introduccion a la F´ısica - Grupo de Física ... · Los bucles en Python En los lenguajes interpretados (como Python) los bucles son lentos. Para realizar c´alculo num´erico es

  • Upload
    buianh

  • View
    217

  • Download
    0

Embed Size (px)

Citation preview

Universidad de OviedoGrado en FısicaCurso 2014-15

Introduccion a la Fısica

Computacional

Tema 4Modulos para calculo cientıfico en Python

IntroduccionExisten numerosos modulos y paquetes que contienencodigo utilizable en calculo cientıfico (e ingenierıa).

Algunos de ellos son Python “puro”. En otrasocasiones ‘debajo’ hay codigo compilado en otroslenguajes (como C o Fortran) y el modulo incluyeuna interface adecuada disenada en Python.

Obviamente, solo analizaremos los comandos masbasicos de los modulos que luego describiremos.

Indice general

Manejo de vectores y matrices con numpy

Representaciones graficas en 2D y 3D

Creacion de escenas realistas en 3D

Calculo numerico y cientıfico con scipy

Comparacion entre Python y Octave/Matlab R©

Indice general

Manejo de vectores y matrices con numpy

Representaciones graficas en 2D y 3D

Creacion de escenas realistas en 3D

Calculo numerico y cientıfico con scipy

Comparacion entre Python y Octave/Matlab R©

Modulo numpy

Este modulo proporciona una manera convenientey eficiente de manejar vectores numericos (losdenominaremos arrays a partir de ahora) en Python.

Los arrays son homogeneos (a diferencia de laslistas de Python que pueden ser heterogeneas): loselementos de un array pueden ser de tipo booleano,entero, real o complejo (pero sin mezclarse).

Un array puede tener varias dimensiones, a las que seaccede por ındices (ordenados).

Motivacion de numpy (ejemplo)En tratamiento de series de datos (temperatura,campo magnetico, etc.) se utiliza a veces la media

movil : sustituir un elemento de la serie por su mediacon puntos anteriores y posteriores.

Por ejemplo, si x es un vector cuyos ındices varıan de0 a n− 1, tendrıamos:

y0 = x0, yn−1 = xn−1,

yi =1

3(xi−1 + xi + xi+1), i = 2, . . . , n− 2

0 200 400 600 800 1000d�a

0

5

10

15

20t º

CTemperaturas en Mieres (ficticias)

Usando listas 1/2# -*- coding: utf-8 -*-

def mediamovil (x):’’’ calcula una media movil de 3 puntos ’’’n = len(x)y = []for i, x1 in enumerate(x):if i == 0 or i == n-1:y.append(x1)

else:y.append((x[i-1]+x1+x[i+1])/3.0)

return y

Usando listas 2/2# lectura de datoslines = open("np01.txt").readlines()x = []for line in lines:if line[0] == "#": continuel = line.split()x.append(float(l[1]))

y = mediamovil(x)# hacemos cuatro medias moviles masfor i in range(4): y = mediamovil(y)

Usando arrays de numpy# -*- coding: utf-8 -*-from numpy import *def mediamovil (x):’’’ calcula una media movil de 3 puntos ’’’y = copy(x)y[1:-1] = (x[0:-2]+x[1:-1]+x[2:])/3.0return y

nx = loadtxt("np01.txt")n, x = nx[:,0], nx[:,1]

y = mediamovil(x)# hacemos cuatro medias moviles masfor i in range(4): y = mediamovil(y)

Los bucles en PythonEn los lenguajes interpretados (como Python) losbucles son lentos. Para realizar calculo numerico esmejor que los bucles esten ‘escondidos’ en codigocompilado (que es mucho mas rapido).

Ası pues, cualquier mecanismo que nos evite losbucles sera muy bienvenido.

Los bucles en lenguajes compilados

La eliminacion de bucles no es especialmentenecesaria en lenguajes compilados como C o Fortran

No obstante, con la llegada de ordenadores convarios procesadores muchas operaciones con arraysse pueden efectuar en paralelo en varios de ellos:idealmente cada procesador se encargarıa de obtenerla solucion para un elemento del array.

Ventajas de usar numpy 1/2numpy nos permite eliminar bucles y eso tambien nosahorra lıneas de codigo (por tanto es mas facil de leer)y el codigo se parece mas a la notacion matematica.

Ademas, si las rutinas de numpy en lenguajecompilado estan desarrolladas para calculo enparalelo tambien nos aprovechamos de los multiplesprocesadores que hubiera en el ordenador.

Ventajas de usar numpy 2/2Tambien, y no menos importante, nos ‘obliga’ apensar en paralelo: las operaciones son las mismassobre diferentes elementos de los vectores.

Los programas codificados con lenguajes ‘paralelos’son normalmente mas cortos, mas claros y mascercanos a las ideas cientıficas que queremosprogramar.

Vectorializar codigoAdaptar el codigo (cuando es posible) para quefuncione en paralelo se denomina vectorializar ovectorizar.

En general consiste en eliminar bucles concontadores.

Mas adelante, cuando conozcamos la sintaxis denumpy y sus posibilidades, veremos ejemplos de comovectorializar codigo.

La estructura basica de datosEn numpy el array es la estructura basica. Consisterealmente en un conjunto homogeneo de datos: int,float (por defecto), etc., que se disponen de maneraadyacente en memoria en forma unidimensional.

Si se requiere que el array tenga dos o masdimensiones, numpy nos proporciona (de maneratransparente) la posibilidad de acceder a loselementos por sus ındices.

Uso de la estructura matrix

Tambien existe la posibilidad de usar la estructuramatrix, aunque creemos mas recomendable usararray en su lugar (sobre todo en los comienzosdel aprendizaje de numpy) pues su uso es mashomogeneo.

Existen muy pocas diferencias entre ambas, laprincipal en la definicion del producto de dos matrices(pero veremos que es muy sencillo con array).

Usando numpy

Se usa numpy de la siguiente manera (por ejemplo):from numpy import *

La mayorıa de las funciones asociadas a numpy queveamos poseen mas argumentos opcionales que losindicados. Para mas informacion debe consultarse:http://docs.scipy.org/doc/numpy/reference/

Manejo de arraysEl manejo de arrays conlleva diversos mecanismos:

Creacion de arrays.

Obtencion de informacion sobre los arrays.

Acceso a elementos y secciones de arrays.

Operaciones con arrays.

Algebra lineal y arrays aleatorios.

Creacion de arraysExisten tres maneras de crear arrays en numpy:

a partir de una lista o tupla (homogenea),

usando una funcion que retorna un array convalores,

leyendo datos desde un fichero.

Usando una lista o tupla: arraySe utiliza la funcion array:

>>> a = array([3, 4, 2]) # 1D

>>> b = array([[3, 2, 4], [3, 3, 2]]) # 2D

>>> print(a)

[4 3 2]

>>> print(b)

[[3 2 4]

[3 3 2]]

Usando una lista: asarrayEn ocasiones en un programa no tenemos claro siun objeto es un array o no y queremos convertirlo aarray. En ese caso es util la funcion asarray:

>>> l = [3, 4, 2]

>>> a = array(l)

>>> print(a)

[4 3 2]

>>> b = asarray(a)

>>> print(b)

[4 3 2]

Conversion de arrays en listasLa operacion inversa (convertir arrays en listas) serealiza con la funcion tolist (OJO tolist(a) nofunciona):>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> a.tolist()

[[3.0, 2.0, 4.0], [3.0, 3.0, 2.0]]

>>> b = array([2., 0., -1.])

>>> b.tolist()

[2.0, 0.0, -1.0]

Funciones basicas que crean arrays

arange es similar a range.linspace produce un array espaciado linealmente.ones genera un array con todo unos.zeros genera un array con todo ceros.eye genera la matriz identidad.

Otras funciones importantespara crear arrayscopy realiza una copia a partir de otro array.concatenate concatena dos arrays.repeat extiende arrays.roll ‘enrolla’ arrays.

Otras funciones que crean arrays

logspace produce un array espaciado de maneralogarıtmica.

mgrid y ogrid generan mallados.

arangearange es similar a range, pero en vez de crearuna lista crea un array y ademas se puede usar unespaciado de tipo float:

>>> a = arange(5)

>>> print(a)

[0 1 2 3 4]

>>> c = arange(1, 2, 0.2)

>>> print(c)

[ 1. 1.2 1.4 1.6 1.8]

linspaceLa funcion linspace produce un array con unnumero determinado de elementos linealmenteespaciados entre dos lımites:>>> b = linspace(1, 2, 6)>>> print(b)[1. 1.2 1.4 1.6 1.8 2.]

A diferencia de arange, se incluyen los extremos.

onesones crea un array con todo unos con el numero deelementos indicados:>>> a = ones(3)>>> print(a)[1.0 1.0 1.0]

Si se pasa como argumento una tupla usa ese numerode elementos en cada dimension:>>> b = ones((3, 2)) # 3 filas, 2 columnas>>> print(b)[[1.0 1.0][1.0 1.0][1.0 1.0]]

zeroszeros crea un array con todo ceros con el numerode elementos indicados:>>> b = zeros((3, 2)) # 3 filas, 2 columnas>>> print(b)[[0.0 0.0][0.0 0.0][0.0 0.0]]

Para mas de una dimension el primer argumento deones y zeros debe ser una tupla (de ahı los doblesparentesis).

zeros likezeros like crea un array con todo ceros con lamisma forma que otro array:>>> a = array([[1, 2, 3, 4], [4, 5, 6, 7]])

>>> b = zeros like(a) # 2 filas, 4 columnas

>>> print(b)

[[0 0 0 0]

[0 0 0 0]]

Tambien existe la funcion ones like que crea unarray con todos unos.

eye: la ‘matriz’ unidadeye crea un array con la diagonal principal llena deunos y el resto de los elementos ceros:>>> b = eye(4, 3) # 4 filas, 3 columnas>>> print(b)[[1.0 0.0 0.0][0.0 1.0 0.0][0.0 0.0 1.0][0.0 0.0 0.0]]

Como vemos, no hace falta que el array sea cuadrado.

Inicializando otras diagonalesTambien se puede indicar que los unos esten porencima o debajo de la diagonal principal usandoun parametro k (0 por defecto: diagonal principal)y puede tomar valores positivos (por encima de ladiagonal principal) y negativos (por debajo):>>> b = eye(5, 4, k = -1)>>> print(b)[[ 0. 0. 0. 0.][ 1. 0. 0. 0.][ 0. 1. 0. 0.][ 0. 0. 1. 0.][ 0. 0. 0. 1.]]

Copiando arrays 1/2Cuando se asigna una variable a un array preexistenteno se copia el array sino que se crea otro nombre parael array:>>> x = array([1, 2, 3])>>> y = x # y es una ’vista’ de x>>> x[0] = 10 # luego veremos esta orden>>> print(y)[10 2 3]

Realmente se puede considerar a y (tambien a x)como una ventana que mira en el verdadero array(un objeto en memoria con caracterısticas de array).

Copiando arrays 2/2Para copiar un array (y asignarle un nombre) se debeusar la funcion copy. En su version mas simple (yusual) serıa:>>> x = array([1, 2, 3])>>> y = copy(x)>>> x[0] = 10>>> print(y)[1 2 3]

El nuevo array al que referencia y no es el mismo queel antiguo x.

concatenate 1/2concatenate((a1, a2, ...), axis=0) concatenaarrays segun una de las dimensiones. La forma de losarrays ha de ser la misma excepto segun la dimensioncorrespondiente a axis (por defecto 0):>>> a = array([[1, 2], [3, 4]])>>> b = array([[5, 6]])>>> concatenate((a, b))>>> # (OJO con los parentesis)array([[1, 2],

[3, 4],[5, 6]])

concatenate 2/2Los arrays 1D concatenan generando un array 1D:>>> x = array([0, 1, 2])>>> y = array([-1, 0.2, 0.9])>>> concatenate((x, y))array([ 0. , 1. , 2. , -1. , 0.2, 0.9])

Si queremos concatenarlos generando varias filas sedebe usar el siguiente ‘truco’:>>> concatenate(([x], [y]))array([[ 0. , 1. , 2. ],

[-1. , 0.2, 0.9]])

(fıjemonos en los corchetes rojos).

repeatrepeat(a, copias, axis) sirve para extenderarrays segun una dimension. En su modo mas simplede funcionamiento conviene indicar la dimension(‘axis’) en la que queremos repetir el array:>>> a = array([[1, 2], [3, 4]])>>> repeat(a, 2, axis=0)array([[1, 2],

[1, 2],[3, 4],[3, 4]])

>>> repeat(a, 2, axis=1)array([[1, 1, 2, 2],

[3, 3, 4, 4]])

roll 1/2roll(a, desplazamiento, axis) desplaza demanera circular los elementos a lo largo deuna dimension. En su modo mas simple defuncionamiento conviene indicar la dimension (‘axis’):>>> a = array([[0, 1, 2, 3], [5, 6, 7, 8]])>>> roll(a, 1, axis=0)array([[5, 6, 7, 8],

[0, 1, 2, 3]])>>> roll(a, -1, axis=1)array([[1, 2, 3, 0],

[6, 7, 8, 5]])

roll 2/2Como vemos la rotacion a lo largo de un eje puedeser hacia atras (desplazamiento negativo).

Si no se indica axis (o se pone axis=None) entoncesel array se convierte a 1D antes de hacer la rotaciony luego se restaura la forma original:>>> a = array([[0, 1, 2, 3], [5, 6, 7, 8]])>>> roll(a, 1)array([[8, 0, 1, 2],

[3, 5, 6, 7]])

logspaceLa funcion logspace produce un array con unnumero determinado de elementos logarıtmicamenteespaciados entre dos lımites:>>> b = logspace(1, 2, 6)>>> print(b)[ 10. , 15.8489319, 25.1188643, 39.8107171,63.0957345, 100. ]

Se incluyen 6 puntos desde 101 hasta 102.

Como en el caso de linspace, se incluyen losextremos.

ogridLa funcion ogrid se usa para generar arrays usadosen mallados. Esta funcion nos devuelve una lista condos arrays, el primero con las coordenadas x y elsegundo con las y:>>> p = ogrid[0:2:0.5, 0:2]>>> print(p)[array([[ 0. ],

[ 0.5],[ 1. ],[ 1.5]]), array([[ 0., 1.]])]

OJO: ogrid no se usa con parentesis.

mgridLa funcion mgrid se usa para generar arrays usadosen mallados. OJO: mgrid no se usa con parentesis.

Se usa ası: m = mgrid[rango x, rango y], siendocada rango:

rango ≡ inicio incluyente : fin excluyente : paso

Nos devuelve un array 3D, siendo m[0,:,:] lascoordenadas x de los puntos y m[1,:,:] las y.

Ejemplo de mgrid>>> m = mgrid[0:2:0.5, 0:2]>>> print(m)[[[ 0. 0. ]

[ 0.5 0.5][ 1. 1. ][ 1.5 1.5]]

[[ 0. 1. ][ 0. 1. ][ 0. 1. ][ 0. 1. ]]]

Leyendo datos de un fichero 1/3Existen varias funciones para leer datos (preparadospreviamente de cierta manera) a partir de ficheros.La funcion basica es loadtxt.

El ejemplo siguiente lee del fichero de texto cuyonombre esta guardado en la variable fname y losincluye en el array out (los argumentos tienen puestoslos valores por defecto):

out = loadtxt(fname, dtype=’float’,comments=’#’, delimiter=None,skiprows=0, usecols=None)

Leyendo datos de un fichero 2/3(Solo se exponen algunos argumentos.)

dtype indica el tipo de dato (entero, real, etc.), pordefecto float.

comments indica un string por el que empiezan laslıneas con comentarios (que se saltan entonces). Pordefecto es #.

Leyendo datos de un fichero 3/3delimiter indica los caracteres que se usan paraseparar datos, por defecto espacios.

skiprows indica cuantas filas iniciales se saltan antesde empezar a leer realmente el array (por defecto 0).Las lıneas de comentarios se cuentan tambien.

usecols indica una secuencia de columnas para leer(por defecto todas), por ejemplo usecols=(1,3,5)

lee solo esas columnas.

# z.txt ------1 2 3

# otro comentario4 5 67 8 9#------------->>> out=loadtxt(’z.txt’, skiprows=2,

usecols=(1,2), dtype=’int’)>>> print(out)[[5 6][8 9]]

>>> b = loadtxt(’z.txt’)>>> print(b)[[ 1. 2. 3.][ 4. 5. 6.][ 7. 8. 9.]]

Obteniendo informacion sobrearraysLos arrays tienen asociados un numero de dimensionesy un tamano a lo largo de cada dimension (‘forma’).

Se accede a esa informacion de diversas maneras,usando ndim, size, shape, len y reshape.

Arrays con ‘vistas’ 1/2Los datos del array (o sea los valores de suselementos) son los mismos independientemente dela forma asociada (puesto que los arrays se guardande manera secuencial en memoria).

Al cambiar la forma de un array se modifica la ‘vista’(o sea, como se ve el array).

Arrays con ‘vistas’ 2/2

Situacion real de a en memoria: 1 2 3 4 5 6

Vista con forma (2,3):1 2 34 5 6

Vista con forma (3,2):1 23 45 6

Todas estas vistas son el mismo array.

Dimensiones de un arrayPara determinar el numero de dimensiones se utilizandim:>>> a = array([[3, 2, 4], [3, 3, 2]])>>> ndim(a)2>>> a.ndim2

Como vemos a.ndim es un dato entero no unafuncion.

Tamano de un arrayPara determinar el numero total de elementos(tamano) se utiliza size:>>> a = array([[3, 2, 4], [3, 3, 2]])>>> size(a)6>>> a.size6

Como vemos a.size es un dato entero no unafuncion.

Forma de un arrayPara determinar la forma, o sea el numero deelementos en cada dimension se utiliza shape:>>> a = array([[3, 2, 4], [3, 3, 2]])>>> shape(a)(2, 3)>>> a.shape(2, 3)

Como vemos a.shape es una tupla de enteros no unafuncion.

La funcion len

Esta funcion aplicada a un array nos da el tamanocorrespondiente a la primera dimension:>>> a = array([[3, 2, 4], [3, 3, 2]])>>> a.shape[0]2>>> len(a)2

igual que se obtendrıa aplicada a listas de listas.

Cambiando la forma 1/2Se puede cambiar la forma de un array con la funcionreshape o asignando una nueva tupla a la variablea.shape:>>> a = array([[3, 2, 4], [3, 3, 2]])>>> a.shape(2, 3)>>> a.shape = (a.size, )>>> print(a)[3 2 4 3 3 2]

Hemos cambiado las dimensiones del array, aunqueno su tamano (o sea 6 en este caso): a.size nopuede cambiar.

Cambiando la forma 2/2En el ejemplo anterior, a partir de este momento elarray tiene una sola dimension y se accede (comoveremos en las transparencias siguientes) con un soloındice:>>> a[0] = 100>>> a.shape = (2, 3)>>> print(a)[[100 2 4][ 3 3 2]]

Vemos que las modificaciones realizadas en a setransmiten aunque se cambie de nuevo la forma.

La traspuesta de un array 1/2Si a es un array, transpose(a), a.transpose() ya.T (que hacen lo mismo), nos devuelven una vistatraspuesta del array a:>>> b = array([[3, 2, 4], [3, 3, 2]])

>>> print(b.T)

[[3 3]

[2 3]

[4 2]]

transpose por defecto invierte todas las dimensiones.

La traspuesta de un array 2/2Se puede indicar el orden exacto de las dimensionesmediante una lista opcional de ejes:>>> b = array([[[3, 2, 4], [3, 3, 2]],

[[-1, -2, -3], [0, 1, 2]]])>>> print(transpose(b,axes=(1,0,2)))[[[ 3 2 4]

[ -1 -2 -3]]

[[ 3 3 2][ 0 1 2]]]

Arrays ‘planos’La funcion ravel nos devuelve una vista de unaunica dimension, mientras que flatten nos devuelveuna copia:>>> b = array([[3, 2, 4], [3, 3, 2]])>>> print(b)[[3 2 4][3 3 2]]

>>> c = ravel(b)>>> print(c)[3 2 4 3 3 2]>>> d = flatten(b)# si modificamos c se modifica b# si modificamos d no se modifica b

Acceso a elementos y seccionesde un arrayPara acceder a partes de un array existen diversosmecanismos:

acceso a un elemento concreto,

vistas de secciones (slices en ingles),

copia de secciones.

Acceso simple a los elementosde un arrayPara acceder a los elementos de un array se usanındices enteros, en lectura o escritura (como acontinuacion):>>> b = array([[3, 2, 4], [3, 3, 2]])

>>> b[1][1] = 10 # una manera

>>> b[0, 0] = 11 # otra manera mas eficiente

>>> print(b)

[[11 2 4]

[3 10 2]]

Secciones de un arrayLa potencia de los arrays se manifiesta en el manejode secciones (slices en ingles) de los mismos.

Las secciones siempre proporcionan vistas, no hacencopia de los arrays.

Una seccion es un bloque (formado por elementosa veces no contiguos) dentro de un array. El bloquese define a traves de patrones que verifican losındices (tantos como dimensiones).

Ejemplo de seccion 1/5Supongamos un array, a, bidimensional por simplificar:

00 01 02 03 0410 11 12 13 1420 21 22 23 2430 31 32 33 34

El primer ındice indicala fila y el segundo lacolumna.

Patron: inicio:final:incremento.El inicio es inclusivo y el final excluyente.(Introduzcase el array a en una consola de Python.)

Ejemplo de seccion 2/5Queremos extraer las columnas impares. Para ellogeneramos un patron de fila : (que indica todo elrango) y uno de columna 0::2.

Se genera una vista de los elementos que estanindicados en rojo y negrita:

00 01 02 03 0410 11 12 13 1420 21 22 23 2430 31 32 33 34

Ejemplo de seccion 3/5Para extraerlo tendrıamos el siguiente codigo:a[:, 0::2] (y tambien a[:, ::2])que genera un array bidimensional:

00 02 0410 12 1420 22 2430 32 34

Ejemplo de seccion 4/5Cualquier modificacion en una seccion del array a semanifiesta en cambios en el propio array a:>>> a[:, 0::2] = 77 # Nota

>>> print(a)

[[77 1 77 3 77]

[77 11 77 13 77]

[77 21 77 23 77]

[77 31 77 33 77]]

Nota: Esa asignacion se denomina broadcasting, yes la conversion de un dato en el necesario en unaoperacion (asignacion a un array en nuestro caso).

Arrays conformablesEste array a[:, 0::2] concreto es conformablecon cualquier array con forma (4, 3).

Eso significa que puede sustituirse donde se necesiteun array de esa forma. Por ejemplo se puede sumar aun array de forma (4, 3).

Tambien se puede multiplicar matricialmente (luegolo veremos) con un array de forma (3, ...).

Ejercicios

1. ¿Que devuelve a[:,::-1]?

2. Obtenga las filas impares de a.

3. Obtenga la vista cuadrada eliminando la ultimacolumna.

4. Obtenga una vista con las dos primeras lıneas.

5. Obtenga una vista con los elementos comunesde las lıneas impares y las columnas impares.

Soluciones

1. a[:, ::-1] devuelve el array donde lascolumnas estan en orden inverso.

2. Mediante a[::2, :].

3. Mediante a[:, :-1] (recuerdese que un finalnegativo es equivalente al final real restandoleel valor indicado).

4. Mediante a[:2, :].

5. Mediante a[::2, ::2].

Copiando seccionesPara generar una copia y no una vista se debeutilizar la funcion copy acompanada de la seleccionde seccion correspondiente:>>> b = copy(a[:, ::2])

>>> print(b)

[[ 0 2 4]

[10 12 14]]

>>> b[0,0] = 1000 # no modifica a[0,0]

Sub-arrays mediante listasSe pueden utilizar tambien listas como patrones deseleccion de secciones de arrays. En este caso seobtiene una copia y no una vista:>>> c = a[:, ::2] # seccion

>>> b = a[:, [0,2,4]] # copia

>>> # tambien b = a[:, range(0,6,2)]

>>> print(b)

[[ 0 2 4]

[10 12 14]]

>>> b[0,0] = 1000 # no modifica a[0,0]

>>> c[0,0] = 2222 # sı modifica a[0,0]

Operaciones con arrays 1/3Existen operaciones, algunas elemento a elemento(en ingles elementwise), y otras resultado de llamadasa funciones que retornan otros arrays o escalares.

Las operaciones basicas son: suma (+), resta (-),multiplicacion (*), division (/), potenciacion (**) ylas comparaciones.

Operaciones con arrays 2/3Tambien se aplican elemento a elemento lasdenominadas funciones universales.

Para poder operar entre sı dos arrays deben tener lamisma forma. Realmente es algo mas complicado,pero no lo describiremos aquı. En el argot delcalculo en paralelo se dice que los arrays deben serconformables.

Operaciones con arrays 3/3Las funciones que devuelven valores son: ‘y‘ logico(all), ‘o’ logico (any), maximo (max), mınimo(min), suma (sum), producto (prod), media (mean),desviacion estandar o tıpica (std), producto matricial(dot), producto vectorial (cross), producto externo(outer).

Suma de arrays 1/2Para poder sumar dos arrays deben tener la mismaforma:>>> a = array([[3, 2, 4], [3, 3, 2]])

>>> b = array([[-3, 2, -4], [0, 1, 2]])

>>> c = a+b

>>> print(c)

[[0 4 0]

[3 4 4]]

>>> print(a+array([1, 2, 3, 4])) # ERROR

La suma de arrays genera un nuevo array.

Suma de arrays 2/2Tambien se puede utilizar el operador += que no creaun nuevo array sino que modifica el que esta a laizquierda:>>> a = array([[3, 2, 4], [3, 3, 2]])

>>> b = array([[-3, 2, -4], [0, 1, 2]])

>>> a += b

>>> print(a)

[[0 4 0]

[3 4 4]]

Resta de arraysPara poder restar dos arrays deben tener la mismaforma:>>> a = array([[3, 2, 4], [3, 3, 2]])

>>> b = array([[-3, 2, -4], [0, 1, 2]])

>>> c = a-b

>>> print(c)

[[6 0 8]

[3 2 0]]

Tambien se puede usar -= de manera similar a +=.

Multiplicacion de arraysPara poder multiplicar (elemento a elemento) dosarrays deben tener la misma forma:>>> a = array([[3, 2, 4], [3, 3, 2]])

>>> b = array([[-3, 2, -4], [0, 1, 2]])

>>> c = a*b

>>> print(c)

[[ -9 4 -16]

[ 0 3 4]]

Tambien se puede usar *= de manera similar a +=.

Division de arraysPara poder dividir (elemento a elemento) dos arraysdeben tener la misma forma:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> b = array([[-3, 2, -4], [1, 2, 1]])

>>> c = a/b

>>> print(c)

[[-1. 1. -1. ]

[ 3. 1.5 2. ]]

Cuidado con la division entre enteros.

Tambien se puede usar /= de manera similar a +=.

Potenciacion de arraysLa potencia tambien se aplica elemento a elementoy los dos arrays deben tener la misma forma:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> b = array([[3, 2, 4], [1, 2, 1]])

>>> c = a**b # tambien c = pow(a, b)

>>> print(c)

[[ 27. 4. 256.]

[ 3. 9. 2.]])

Tambien se puede usar **= de manera similar a +=.

Broadcasting 1/3El termino broadcasting describe como trata numpy

arrays de diferentes formas en las operacionesaritmeticas (vease la documentacion de numpy).

Dos dimensiones son compatibles cuando son igualeso cuando una de ellas es 1.

Los arrays de menos dimensiones se extienden enlas dimensiones restantes para tener las mismasdimensiones que los arrays ‘mas grandes’.

Broadcasting 2/3Un escalar siempre se puede operar con cualquierarray:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> print(a+2)

[[ 5. 4. 6.]

[ 5. 5. 4.]]

>>> print(2**a)

[[ 8. 4. 16.]

[ 8. 8. 4.]]

Broadcasting 3/3Pongamos dos ejemplos con arrays de diferentestamanos:>>> a = array([[3., 2., 4.], [3., 3., 2.]])>>> b = array([10, 11, 12])>>> # a.shape = (2, 3), b.shape = (3,)>>> print(a+b)[[ 13. 13. 16.][ 13. 14. 14.]]

>>> g = array([[100],[200]])>>> # g.shape = (2, 1)>>> print(a+g)[[ 103. 102. 104.][ 203. 203. 202.]]

Comparacion de arrays 1/2Las operaciones de comparacion que devuelven arrayscon valores logicos:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> b = a > 2

>>> print(b)

[[ True False True]

[ True True False]]

Comparacion de arrays 2/2No obstante, si los operadores de comparacion seusan en una operacion, True se convierte en 1 yFalse se convierte en 0:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> c = 9*(a > 2)

>>> print(c)

[[9 0 9]

[9 9 0]]

La funcion where 1/2La funcion where esta relacionada con lasoperaciones condicionales. Cuando se invoca conun unico argumento devuelve una tupla con losındices de los elementos del array donde se cumplela condicion:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> d = where (a > 2)

>>> print(d)

(array([0, 0, 1, 1]), array([0, 2, 0, 1]))

La funcion where 2/2Cuando where se invoca con tres argumentossustituye los valores que cumplen una condicion porun cierto valor y los que no por otros:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> g = where (a > 2, a**2, -1.0)

>>> print(g)

[[ 9. -1. 16.]

[ 9. 9. -1.]]

Funciones universales 1/3Estas funciones, denominadas en ocasiones ‘puras‘y en el argot de Python ufuncs, no tienen efectoslaterales (no modifican por ejemplo ninguna variableglobal ni manejan ficheros).

Por ejemplo, sin es una ufunc. Lo son tambien lamayorıa de las funciones matematicas que se aplicansobre escalares.

Las ufuncs se aplican elemento a elemento.

Funciones universales 2/3Las funciones del modulo math estan redefinidas ennumpy para que el calculo sea elemento a elementode los arrays, y ademas sea muy rapido:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> c = a+3*sin(a)*log(a)

>>> print(c)

[[ 3.46510853 3.89083084 0.8525469 ]

[ 3.46510853 3.46510853 3.89083084]]

Las ufuncs crean nuevos arrays.

Funciones universales 3/3Entre las funciones universales se tienen: absolute,add, arccos, arccosh, arcsin, arcsinh, arctan,arctan2, arctanh, ceil, conj, cos, cosh,deg2rad, divide, exp, exp2, floor, fmod, hypot,log, log10, log2, mod, multiply, negative,power, rad2deg, reciprocal, remainder, rint,sign, sin, sinh, sqrt, square, subtract, tan,tanh, trunc.

Definicion de funciones quetienen como argumentos arraysEn ocasiones necesitamos definir funciones que usencomo argumentos arrays. Deben ser funciones puras.Por ejemplo:>>> def f (a):. . . return a+3*sin(a)*log(a). . .>>> a = array([[3., 2., 4.], [3., 3., 2.]])>>> f(a)array([[ 3.46510853, 3.89083084, 0.8525469 ]

[ 3.46510853, 3.46510853, 3.89083084]])

Vectorizando funciones 1/4No obstante, no todas las funciones puras quedisenemos para escalares pueden ser invocadasdirectamente con arrays. Por ejemplo:>>> def h (a):

. . . return a if a > 2 else -a

. . .

>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> h(a)

ValueError: The truth value of an array . . .

Vectorizando funciones 2/4Se necesita vectorizar la funcion. Ello se hace conun decorador, que es otra funcion que se invocapreviamente a la nuestra (y que hace ‘cosas’ con ella).

En nuestro caso se puede poner @vectorize en lalınea anterior a def h(a):.

Si ya se ha definido la funcion, se puede usarla funcion decoradora (vectorize) para crear unanueva funcion.

Vectorizando funciones 3/4>>> hh = vectorize(h) # hh es h ’decorada’>>> hh(a)array([[ 3., -2., 4.],

[ 3., 3., -2.]])>>> # decoracion directa:>>> @vectorize>>> def g (a):. . . return a if a > 2 else -a. . .>>> g(a)array([[ 3., -2., 4.],

[ 3., 3., -2.]])

Vectorizando funciones 4/4La vectorizacion de funciones no es necesaria cuandoaparecen operaciones basicas y llamadas a ufuncs,como en el caso arriba expuesto:def f (a): return a+3*sin(a)*log(a)

Es mas, en este caso vectorizar f es contraproducentepuesto que tarda mas la llamada que en el casopresente.

Recomendacion: no vectorizar; si el interprete da unerror de vectorizacion, entonces vectorizar la funcionque lo necesite, o redisenar el codigo fuente.

Funciones que devuelven valores 1/2

all, ‘y’ logico con los elementos de un array.any, ‘o’ logico con los elementos de un array.min, el mınimo elemento de un array.max, el maximo elemento de un array.sum, la suma de los elementos del array.prod, el producto de los elementos del array.mean, la media de los elementos del array.std, la desviacion estandar de los elementos del array.

Funciones que devuelven valores 2/2

dot, el producto escalar y producto matricial.cross, el producto vectorial.outer, el producto externo.diag, devuelve diagonales de un array.

‘y’ logicoLa funcion all realiza un ‘y’ logico (and) con todoslos elementos de un array (o con los elementos a lolargo de un eje):>>> a = array([[3, 2, 4], [3, 3, 0]])

>>> a.all()

False

>>> b = a.all(axis=1)

>>> print(b)

[ True False]

Recordemos que 0 (y 0.0) se toma como valor Falsey otro valor como True.

‘o’ logicoLa funcion any realiza un ‘o’ logico (or) con todoslos elementos de un array (o con los elementos a lolargo de un eje):>>> a = array([[3, 2, 4], [3, 3, 0]])

>>> a.any()

True

>>> c = a.any(axis=1)

>>> print(c)

[ True True True]

Recordemos que 0 (y 0.0) se toma como valor Falsey otro valor como True.

Mınimo y maximo 1/2a.min() (OJO min(a) no funciona) nos devuelve elmınimo valor del array. a.max() (OJO max(a) nofunciona) nos devuelve el maximo valor del array.>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> a.min()

2.0

>>> a.max()

4.0

Mınimo y maximo 2/2Tambien se pueden pedir mınimos y maximos a lolargo de algun eje:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> a.min(axis=0)

array([ 3., 2., 2.])

>>> a.max(axis=1)

array([ 4., 3.])

Suma y productoSon similares a min, pero devuelven la suma (sum) yel producto (prod) de los elementos del array:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> a.sum(axis=0)

array([ 6., 5., 6.])

>>> a.prod(axis=1)

array([ 24., 18.])

Media y desviacion estandarSon similares a min, pero devuelven la media (mean) ydesviacion estandar (std) de los elementos del array:>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> a.mean(axis=1)

array([ 3. , 2.66666667])

>>> a.std()

0.68718427093627676

Producto escalarEl producto escalar de dos vectores se obtienemediante la funcion dot:>>> a = array([3., 2., 4., 0.])

>>> b = array([2., 0., -1., 2.])

>>> dot(a, b)

2.0

El tamano de ambos arrays debe ser el mismo.

Producto matricial 1/2dot tambien se usa para realizar el producto dematrices (no confundir con el producto elemento aelemento visto antes):>>> a = array([[3., 2., 4.], [3., 3., 2.]])

>>> b = array([2., 0., -1.])

>>> dot(a, b)

array([ 2., 4.])

Producto matricial 2/2Para poder multiplicar dos arrays, a y b, comomatrices, el numero de elementos a lo largo de laultima dimension de a debe ser igual al numero deelementos de la primera dimension de b:>>> a.shape

(2, 3)

>>> b.shape

(3,)

Producto vectorialEl producto vectorial de dos vectores de 3 elementosse obtiene mediante la funcion cross:>>> x = array([1, 2, 3])

>>> y = array([-1, 2, -4])

>>> cross(x, y)

array([-14, 1, 4])

El tamano de ambos arrays debe ser 3.

Producto externoDados dos vectores, a de longitud M y b de longitudN, se define de la siguiente manera:

cik = aibk, i = 0, . . . ,M − 1, k = 0, . . . , N − 1.

Para calcularlo se utiliza la funcion outer:>>> a = array([1, 2, 3])

>>> b = array([-1, 2])

>>> outer(a, b)

array([[-1, 2],

[-2, 4],

[-3, 6]])

Diagonal de un arrayLa funcion diag nos devuelve la diagonal de un array:>>> a = array([[1, 2, 3, 4], [5, 6, 7, 8]])

>>> print(a)

[[1 2 3 4]

[5 6 7 8]]

>>> diag(a)

array([1, 6])

>>> diag(a, k=1) # 1 encima de la principal

array([2, 7])

Interes de vectorializar el codigo

Eliminar ındices del codigo es posible siempre que lasexpresiones se puedan evaluar a la vez para cualquierındice (si no es ası no se puede vectorializar el codigo).

Siempre que se eliminen del codigo ındices que debanser iterados con un bucle tanto mejor (en cualquierlenguaje interpretado al menos).

Pero eliminar ındices implica gastar mas memoria yrepensar el codigo (lo que a veces es difıcil).

Ejemplos de vectorializacion deexpresionesAnalizaremos varios casos, algunos con mascontenido fısico que otros:

Un caso simple.Integracion por rectangulos.Serie radiactiva.Eliminacion sucesiva de ındices.Tratamiento de un caso con excepciones.Ecuacion de Poisson en 2D.Difusion de neutrones en 1D.

Un caso simpleSea b un array cuadrado de forma (n, n). Laexpresion:

cik = bik + bi+1,k+1,

{

i = 0, . . . , n− 2,k = 0, . . . , n− 2,

se codifica:

c[:-1,:-1] = b[:-1,:-1] + b[1:,1:]

Integracion por rectangulos 1/3Se define la integral de Riemann de una funcion f(x)entre dos abscisas a y b mediante:

I =

∫ b

a

f(x)dx.

a b

y

x

I

f (x)

Integracion por rectangulos 2/3La solucion de este problema puede obtenersenumericamente por el metodo de los rectangulos:

I ≈ h

n−1∑

i=0

f

(

a+1

2h+ ih

)

h =b− a

n,

a b

y

x

f (x)

h

0 ...1 i n −1

Integracion por rectangulos 3/3Se puede usar la siguiente funcion:

def integra (f, a, b, n=100):

h = (b-a)/float(n)

x = linspace(a+0.5*h, b-0.5*h, n)

return h*sum(f(x))

La vectorializacion va implıcita en la llamada a lafuncion f para luego realizar la suma.

Serie radiactiva 1/3Las series radiactivas sin bifurcaciones estanformadas por radionuclidos que se desintegran unosen otros: 0 → 1 → 2 → . . . → n, siendo el nuclido nestable. Si Ni es el numero de nucleos presentes delradionuclido i se tiene:

N0 = − λ0N0,

Ni = λi−1Ni−1 − λiNi.

λi es la denominada constante de desintegracion delradionuclido i.

Serie radiactiva 2/3Se puede poner en forma matricial:

N =

−λ0 0 0 . . . 0λ0 −λ1 0 . . . 00 λ1 −λ2 . . . 0. . . . . . . . . . . .0 0 0 . . . −λn−1

N.

Serie radiactiva 3/3Se vectorializa de la siguiente manera. Tenemos L

como vector con las λ, y N como vector de numerode nucleos:

n = N.size # n = L.size, tambien

Np = dot((eye(n, n, k=-1)-eye(n, n))*L, N)

Al operar con L y N se realiza broadcasting.

Eliminacion sucesiva de ındices 1/2

Sea x un vector de longitud n. La expresion:

wi =

n−1∑

k=0

|xi + xk|, i = 0, . . . , n− 1,

se puede codificar:w = zeros like(x)indices = range(len(x))for i in indices:w[i] = sum(abs(x[i]+x))

Eliminacion sucesiva de ındices 2/2

Pero tambien mediante:n = len(x)x.shape = (n, 1)aux = x.repeat(n, axis = 1)w = sum(abs(aux+aux.T), axis = 0)

Este segundo metodo necesita mucha mas memoria(el array bidimensional aux al menos) que el primero,pero es mas rapido, ya que no lleva bucles.

Tratamiento de un caso conexcepciones 1/2Sea x un vector de longitud n. La expresion:

wi =

n−1∏

k=0,k 6=i

(xk − xi), i = 0, . . . , n− 1,

(la excepcion es que k 6= i) se puede codificar:w = zeros like(x)indices = range(len(x))for i in indices:w[i] = prod(where(x != x[i], x-x[i], 1.0))

Tratamiento de un caso conexcepciones 2/2Pero es mas rapido el trozo de codigo siguiente:

n = len(x)x.shape = (n, 1)aux = x.repeat(n, axis = 1)aux = aux-aux.Tw = prod(where(aux != 0, aux, 1.0), axis = 0)

Como vemos, la eliminacion de un ındice ‘que sepierde’ (k cuando es igual al i) conlleva la utilizacionde la funcion where, como mascara.

Ecuacion de Poisson en 2D 1/3La ecuacion de Poisson del electromagnetismo es en2D:

∂2V

∂x2+

∂2V

∂y2= − ρ

ǫ0,

siendo V el potencial electrico y ρ la densidad decarga en cada punto del recinto.

Ecuacion de Poisson en 2D 2/3Discreticemos un recinto rectangular con un malladoh, con nx nodos en Ox y ny nodos en Oy, de talmanera que V (i, k) define el potencial en los puntosi = 0, 1, . . . , nx−1, k = 0, 1, . . . , ny−1. El problemade Dirichlet (potencial conocido en la frontera) sepuede resolver iterando en m:

V m+1i,k =

1

4

(

V mi+1,k + V m

i−1,k + V mi,k+1 + V m

i,k−1 +h2

ǫ0ρi,k

)

i = 1, 2, . . . , n− 2, k = 1, 2, . . . , n− 2.

Ecuacion de Poisson en 2D 3/3

Denominando K a h2/ǫ0, y R a ρ tendrıamos:Vn[1:-1,1:-1] = (V[2:,1:-1]+V[:-2,1:-1]+

V[1:-1,2:]+V[1:-1,:-2]+

K*R[1:-1,1:-1])/4

El potencial en los bordes no se calcula en estaexpresion (no varıa con el tiempo). Para el siguientepaso temporal se hace:V[1:-1,1:-1] = copy(Vn[1:-1,1:-1])

Difusion de neutrones en 1D 1/3

En un reactor nuclear de fision (en 1D parasimplificar) si denominamos y a la cantidad deneutrones presentes, C a su tasa de creacion y Dal coeficiente de difusion, se verifica la siguienteecuacion diferencial en derivadas parciales:

∂y

∂t= D

∂2y

∂x2+ Cy.

Se supone que y(x = 0) = y(x = L) = 0, siendox = 0 y x = L los bordes del recinto.

Difusion de neutrones en 1D 2/3

Esta ecuacion se puede discretizar en el espaciousando n intervalos, de tal manera que h = L/n,y en el tiempo usando un incremento temporal τ .Con i = 1, 2, . . . , n− 2 tendrıamos:

ym+1i = ymi +

h2(ymi+1 + ymi−1 − 2ymi ) + Cτymi .

Este metodo permite estudiar el problema dela criticidad (automantenimiento de la reaccionnuclear) variando D, C y la condicion inicial, y0i .

Difusion de neutrones en 1D 3/3

Denominando K a Dτ/h2, y R a 1 + Cτ − 2Ktendrıamos:

yn[1:-1] = R*y[1:-1] + K*(y[2:]+y[:-2])

Para el siguiente paso temporal se hace:

y[1:-1] = copy(yn[1:-1])

Indice general

Manejo de vectores y matrices con numpy

Representaciones graficas en 2D y 3D

Creacion de escenas realistas en 3D

Calculo numerico y cientıfico con scipy

Comparacion entre Python y Octave/Matlab R©

Graficas en 2DExisten diversos paquetes de modulos para representargraficas en 2D y 3D. Usaremos el paqueteMatplotlib, considerado como una especie de‘estandar’.

Para representaciones en 2D usaremos el moduloMatplotlib.pyplot, que contiene una coleccion defunciones que son similares a las usadas en Matlab R©.

Mas informacion esta disponible enhttp://matplotlib.sourceforge.net/

Como funciona MatplotlibMatplotlib tiene el concepto de ‘figura actual’,tambien con el ‘area de dibujo actual’ y ‘ejesactuales’, pudiendo cambiarse en cada momentocualquiera de ellos.

Una figura puede contener subfiguras (diferenteszonas de dibujo), y se pueden anotar con tıtulos,tıtulos de ejes, etc.

El modulo de dibujo es matplotlib.pyplot

Como usar pyplotPara evitar ‘contaminaciones’ del espacio global devariables y funciones lo importaremos ası:

import matplotlib.pyplot as plt

El primer comando grafico que empleemos crea unafigura a la que iran los elementos graficos que sevayan anadiendo.

Para crear expresamente una nueva figura usaremos

plt.figure()

Salida interactiva o a ficheroLos comandos graficos no se iran mostrando enpantalla hasta que se utilice el comando

plt.show()

Sin embargo es posible que no nos interese mostrarlos resultados en pantalla sino en un fichero graficocon el comando

plt.savefig()

Un ejemplo simple# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

plt.plot([1,2,3,4], [1,4,9,16])

plt.title(’Una figura simple’)

plt.xlabel(u’algunos numeros’)

plt.ylabel(’cuadrados’)

plt.show()

La u inicial de u’algunos numeros’ sirve paraintroducir una cadena de caracteres Unicode, con loque se permiten acentos, enes, etc.

Ejercicio 1Realice la representacion grafica de los puntos:

(1, 2), (2, 6), (3.3, 5.4), (4.9, 6.7),

etiquetando el eje Ox con ‘x’ y el eje Oy con ‘dıas’.

El tıtulo de la figura debe ser ‘Figura 14.34’.

Una solucion# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

puntos = [(1.1, 2.1), (2, 6),

(3.3, 5.4), (4.9, 6.7)]

x = [p[0] for p in puntos]

y = [p[1] for p in puntos]

plt.plot(x, y, ’s’)

plt.xlabel(’x’)

plt.ylabel(u’dıas’)

plt.title("Figura 14.34")

plt.show()

Salida grafica del ejercicio

1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5 5.0x

2

3

4

5

6

7d�

asFigura 14.34

Dibujo de funciones 1/2Para dibujar funciones necesitamos obtener dos listas(o vectores) con las x y las y de puntos de la curva:import matplotlib.pyplot as plt

x = [0.2*i for i in range(25)]

x3 = [v**3 for v in x]

plt.plot(x, x, ’bs’) # dibuja y = x

plt.plot(x, x3, ’r^’) # dibuja y = x3

plt.xlabel(’x’); plt.ylabel(’y’)

plt.axis([0, 6, 0, 80])

plt.show()

Dibujo de funciones 2/2plt.plot(x, x, ’bs’) indica que queremos dibujaruna curva con los puntos cuyas abscisas y ordenadasvienen dadas por x, en color azul (b) con cuadrados(‘squares’); plt.plot(x, x3, ’r^’) otra curva encolor rojo (r) con triangulos (ˆ) en la que las abscisasson x y las ordenadas los cubos de las abscisas.

plt.axis([0, 6, 0, 80]) indica que los ejestienen los lımites xmin = 0, xmax = 6, ymin = 0,ymax = 80.

Salida grafica del ejemplo

0 1 2 3 4 5 6x

0

10

20

30

40

50

60

70

80y

Ejercicio 2Realice la representacion grafica de la funcion cos xusando 50 puntos entre 0 y 10. Etiquete el eje Oxcon ‘x’ y el eje Oy con ‘cos(x)’.

El tıtulo de la figura debe ser ‘La funcion coseno’.

Una solucion# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

from math import cos

xmax = 10.0; delta = xmax/50

x = [delta*i for i in range(51)]

cx = [cos(v) for v in x]

plt.plot(x, cx, ’b-’)

plt.xlabel(’x’)

plt.ylabel(’cos(x)’)

plt.title(u"La funcion coseno")

plt.show()

Salida grafica del ejercicio

0 2 4 6 8 10x

�1.0

�0.5

0.0

0.5

1.0co

s(x)

La funci�n coseno

Control de los ejesLos ejes se controlan con el comando axis, comoantes hemos visto. Sin embargo se puede indicar conuna cadena de caracteres otros lımites automaticos.

Por ejemplo, para hacer que ambos ejes tenganunidades iguales se utiliza

plt.axis(’equal’)

De esta manera las circunferencias parecen realmentecirculares.

Un ejemplo con ejes iguales# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

from math import cos, sin

from numpy import *

ang = linspace(0, 2*pi, 50)

r = 3.0

plt.plot(r*cos(ang), r*sin(ang), ’b-’)

plt.xlabel(’x’); plt.ylabel(’y’)

plt.title("Una circunferencia")

plt.axis(’equal’)

plt.show()

Salida grafica del ejemplo

�3 �2 �1 0 1 2 3x

�3

�2

�1

0

1

2

3y

Una circunferencia

Etiquetando las curvasSe pueden incluir leyendas para etiquetar las curvasmediante la orden legend. Para ello previamente hayque dibujar la curva incluyendo un argumento label:plt.plot(x, x3, ’r^’, label=’x^3’)

y luego usar:plt.legend()

Se pueden proporcionar tambien argumentos alegend para indicar la posicion de la leyenda y otrosatributos.

Problema 1Anada a la figura del ejercicio 2 previamente resueltola curva de sin x en el mismo rango, en color rojo ycon rayas discontinuas.

Etiquete la figura con ‘funciones trigonometricas’ conla leyenda correspondiente (‘cos x’, ‘sin x’) para lasdos curvas.

Problema 2Disene una funcion denominada funplot que dibujeuna funcion f entre dos abscisas, xmin, xmax usandoen total np puntos. Tambien se le debe pasar eltipo de lınea y la leyenda (que no dibujara si no seproporciona).

Guardando la figuraEl comando savefig guarda la figura en un ficherografico para su posterior manipulacion con otrosprogramas.

Si le ponemos un nombre de fichero con una extensioncomo emf, eps, pdf, png, ps, y otros, guardara elfichero con ese formato:

plt.savefig("velocidad.eps")

(Consultese el manual para otras opciones.)

Controlando propiedades de laslıneasSe pueden controlar las propiedades de las lıneasusando la funcion setp. Para ello debe invocarse aplot mediante:lines = plt.plot(x, x, ’bs’, x, x3, ’r^’)

Poir ejemplo, para cambiar el estilo de la lınea:plt.setp(lines, linestyle = ’:’)

(Vease el manual de referencia de Matplotlib para tener

una lista de las propiedades modificables.)

Varias subfigurasSe pueden dibujar en la misma figura varias graficas(con diferentes ejes cada una) usando el comandosubplot, que se invoca de la siguiente manera:

plt.subplot(numfilas, numcolumnas, numfigura)

Las figuras se numeran de izquierda a derecha yde arriba abajo. plt.subplot(2, 4, ...) serıa laorden para dos filas y cuatro columnas, numeradas:1 2 3 45 6 7 8

Un ejemplo con subfigurasimport matplotlib.pyplot as plt

from numpy import *

def f(t): return exp(-t)*cos(2*pi*t)

t1 = arange(0.0, 5.0, 0.1)

t2 = arange(0.0, 5.0, 0.02)

plt.subplot(2,1,1)

plt.plot(t1, f(t1), ’bo’, t2, f(t2), ’k’)

plt.subplot(2,1,2)

plt.plot(t2, cos(2*pi*t2), ’r--’)

plt.show()

Salida grafica del ejemplo

0 1 2 3 4 5�0.8�0.6�0.4�0.20.00.20.40.60.81.0

0 1 2 3 4 5�1.0

�0.5

0.0

0.5

1.0

Otros comandos de dibujo (hay mas)

hist para dibujar histogramas

bar para representar barras verticales

errorbar para dibujar barras de error

loglog para usar ejes logarıtmicos

semilogx para usar eje Ox logarıtmico

semilogy para usar eje Oy logarıtmico

scatter para realizar diagramas de dispersion

polar para diagramas polares

contour para dibujar lıneas de contorno

contourf para dibujar rellenos de contorno

quiver para dibujar campos vectoriales

Un ejemplo de contourfimport matplotlib.pyplot as plt

from numpy import ogrid

# ogrid retorna un mallado bidimensional

x,y = ogrid[-1:1:0.01, -1:1:0.01]

z = 3*y*(3*x**2-y**2)/4

plt.contourf(z, extent=[-1,1,-1,1])

plt.show()

Salida grafica del ejemplo

�1.0 �0.5 0.0 0.5 1.0�1.0

�0.5

0.0

0.5

1.0

Ejercicio 3La funcion y = axb se representa mejor conescalas logarıtmicas en ambos ejes, usando loglog

(realmente sale una recta).

Realice la representacion grafica de la funcion anteriorcon a = 10.0, b = 0.3, entre 10−3 y 10 usando 50puntos.

Una solucion# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

a, b = 10.0, 0.3

xmin, xmax, np = 1.0e-3, 10.0, 50

delta = (xmax-xmin)/np

x = [xmin+delta*i for i in range(51)]

y = [a*v**b for v in x]

plt.loglog(x, y, ’b-’)

plt.xlabel(’x’)

plt.ylabel(’y’)

plt.show()

Salida grafica del ejercicio

10-3 10-2 10-1 100 101x

100

101

102y

Anotando figurasSe puede incluir una cadena de caracteres en un punto(xt, yt) mediante el comando text:

plt.text(xt, yt, "Turner")

Se puede anadir una flecha usando annotate:

plt.annotate("Lin", xy = (xa, ya), xytext = (xt, yt),

arrowprops=dict(facecolor=’black’, shrink=0.05, width=1))

que coloca el texto en las coordenadas (xt, yt), conuna flecha que tiene su punta en (xa, ya).

Ejercicio 4Dibuje la funcion y = 0.2 exp(−(x + 3)2) entre lasabscisas −5 y 0, y las ordenadas 0 y 0.3, etiquetandoel maximo de la funcion con ‘maximo’ y una flechaindicativa.

Una solucion# -*- coding: utf-8 -*-

import matplotlib.pyplot as plt

from math import exp

xmin, xmax, ymin, ymax, np = -5.0, 0.0, 0.0, 0.3, 50

delta = (xmax-xmin)/np

x = [xmin+delta*i for i in range(np+1)]

y = [0.2*exp(-(v+3.0)**2) for v in x]

plt.plot(x, y, ’b-’)

plt.xlabel(’x’); plt.ylabel(’y’)

plt.axis([xmin, xmax, ymin, ymax])

plt.annotate(u"maximo", xy = (-3.0, 0.2), xytext = (-1.5, 0.25),

arrowprops=dict(facecolor=’black’, shrink=0.05, width=1))

plt.show()

Salida grafica del ejercicio

�5 �4 �3 �2 �1 0x

0.00

0.05

0.10

0.15

0.20

0.25

y

m�ximo

Graficas en 3DPara visualizacion de curvas y superficies en 3Dusaremos el modulo matplotlib.mplot3d.

Evidentemente no existe posibilidad fısica derepresentar en 3D sino que se recurre a proyeccionessobre la pantalla (2D).

Mas informacion esta disponible enhttp://matplotlib.sourceforge.net/

mpl toolkits/mplot3d/tutorial.html

Usando mplot3d

Para usar ese modulo se debe usar el submoduloAxes3D de la manera siguiente:

import matplotlib.pyplot as plt

from mpl toolkits.mplot3d import Axes3D

Luego se asocia la figura que se crea con el comandoAxes3D a unos ejes, ax, en 3D:

fig = plt.figure()

ax = Axes3D(fig)

Dibujo de curvas con mplot3d

Ahora ya se pueden dibujar curvas proyectadas en lapantalla mediante:

ax.plot(x, y, z, label=’una curva’)ax.legend()plt.show()

(obviamente despues de definir los vectores x, y, z)

Un ejemplo de curva en 3Dfrom mpl toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

from numpy import *

fig = plt.figure()

ax = Axes3D(fig)

th = linspace(-4*pi, 4*pi, 100)

z = linspace(-2, 2, 100)

r = z**2 + 1; x = r*sin(th); y = r*cos(th)

ax.plot(x, y, z, label=’una curva’)

ax.legend()

plt.show()

Salida grafica del ejemplo

4 3 2 1 0 1 2 3 4 321

01

23

4

1.5

1.0

0.5

0.0

0.5

1.0

1.5

una curva

Superficies con mplot3d

Tambien se pueden dibujar superficies proyectadas enla pantalla mediante ax.plot surface(x, y, z).

El mapa de colores que se asocian a los valores de zse puede variar, usando por ejemplo los suministradosen el modulo cm que se importa mediante

from matplotlib import cm

Veamos ahora el mismo ejemplo que hemosrepresentado antes con contourf.

Un ejemplo de superficie en 3Dfrom mpl toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

from matplotlib import cm

from numpy import *

fig = plt.figure()

ax = Axes3D(fig)

xv = arange(-1, 1, 0.05); yv = arange(-1, 1, 0.05)

x, y = meshgrid(xv, yv); z = 3*y*(3*x**2-y**2)/4

ax.plot surface(x, y, z, rstride=1, cstride=1, cmap=cm.jet)

ax.set xlabel("x"); ax.set ylabel("y"); ax.set zlabel("z")

plt.show()

Salida grafica del ejemplo

x0.5

0.00.5

y0.5

0.0

0.5

z

1.0

0.5

0.0

0.5

1.0

Salida grafica con contourf

�1.0 �0.5 0.0 0.5 1.0�1.0

�0.5

0.0

0.5

1.0

Ejercicio 5Dibuje la funcion

z = 0.2 sinx exp(−(x+ 3)2) exp(−(y + 2)2)

con x ∈ [−0, 0], y ∈ [−5, 0].

Una solucionfrom mpl toolkits.mplot3d import Axes3D

import matplotlib.pyplot as plt

from matplotlib import cm

from numpy import *

fig = plt.figure(); ax = Axes3D(fig)

xv = arange(-5, 0, 0.1); yv = arange(-5, 0, 0.1)

x, y = meshgrid(xv, yv)

z = 0.2*sin(x)*exp(-(x+3)**2)*exp(-(y+2)**2)

ax.plot surface(x, y, z, rstride=1, cstride=1, cmap=cm.jet)

ax.set xlabel("x"); ax.set ylabel("y"); ax.set zlabel("z")

plt.show()

Salida grafica del ejercicio

x

�4�3

�2�1

y

�4�3

�2�1

z

�0.08

�0.06

�0.04

�0.02

0.00

0.02

0.04

0.06

Problema 3Represente la funcion z = (sin x)(sin 3y) en el rangox ∈ [0.1, 1.1], y ∈ [0.1, 1.1].

Indice general

Manejo de vectores y matrices con numpy

Representaciones graficas en 2D y 3D

Creacion de escenas realistas en 3D

Calculo numerico y cientıfico con scipy

Comparacion entre Python y Octave/Matlab R©

Escenas realistas en 3DVPython (con el modulo visual) es una herramientapara producir escenas realistas con movimiento en3D.

La documentacion de visual se puede encontrar enhttp://vpython.org y un tutorial enhttp://vpython.org/contents/docs/visual/VPython Intro.pdf

visual utiliza el concepto de ventana de visualizacionla cual se proyecta sobre la pantalla (2D).

La ventana de visualizacion(0,0,0) es el origen de la ventana. Por defecto eleje +x es horizontal hacia la derecha, el +y es verticalhacia arriba y el +z apunta hacia afuera de la pantallahacia el observador.

Las coordenadas x, y, z se miden en las unidadesque se deseen. Entonces la visualizacion se escala demanera adecuada a la escena.

ObjetosLos objetos creados mantienen su existencia durantela ejecucion del programa.

Se debe dar a cada objeto un nombre (como bola

o caja) si deseamos usarlo mas adelante en elprograma:from visual import *

caja=box(pos=vector(4,2,3),

size=(8,4,6), color=color.red)

bola=sphere(pos=vector(4,7,3), radius=5,

color=color.green)

Salida grafica del ejemplo

Modificando el punto de vistaSe puede girar el “mundo” pulsando el boton derechodel raton en la ventana de VPython que generavisual y arrastrando sin soltar el boton.

Tambien se puede “ver” la escena desde mas cera olejos. Para ello se pulsa el boton central del raton yse arrastra (en ratones con dos botones se pulsan ala vez los mismos).

Para acabar el programa debe cerrarse la ventanagrafica.

Controlando la visualizacion 1/3Tambien se pueden definir mediante el programadiversos atributos de la pantalla de visualizacion.

Para ello se utiliza display, que crea una figuracon los atributos especificados y retorna una variablefigura que luego se puede usar.

Controlando la visualizacion 2/3Por ejemplo:

escena = display(title="Cubo",

width=600, height=200,

center=(5,0,0), background=(0,1,1))

crea una ventana de 600 por 200 con el tıtulo“Cubo”, centrada en la posicion (5, 0, 0) con un colorde fondo cyan.

Si no se da nombre (escena en nuestro caso)entonces visual le da el nombre generico scene.

Controlando la visualizacion 3/3Se pueden cambiar otras caracterısticas de escena

mediante (luego veremos la funcion vector):

# proporcion de luz ambiente (por defecto 0.2)escena.ambient = 0.7

# direccion de la iluminacionescena.lights = [vector(0,0.3,0) ]

# direccion desde donde mira la "camara"escena.forward=vector(0.1,-0.10,0.0)

# campo de vision de la camara en radianesescena.fov=1e-14 # aproximadamente ortogonal

AtributosLos objetos tienen atributos, propiedades comola posicion (bola.pos), el color (bola.col), elradio (bola.radius) u otros parametros de tamano(dependientes del objeto).

Podemos asignar valores de atributos a los objetoscuando se crean mediante su constructor (comoen el ejemplo anterior) y se pueden modificar masadelante: bola.radius = 10. Al cambiar el atributode un objeto, visual cambia automaticamente lapresentacion del mismo.

Atributos creados por el usuarioAdemas del conjunto de atributos que existen al crearun objeto, se pueden crear nuevos atributos. Si se creauna esfera denominada marte, aparte de su radio,color y localizacion se pueden crear otros atributoscomo marte.masa, marte.velocidad, etc.

Esto sirve para que los programas que usen visual

tengan una enfoque orientado a objetos y facilitan eluso y lectura del codigo.

Creacion de vectores 3DSe pueden crear magnitudes vectoriales 3D y realizaroperaciones con ellas (por ejemplo asignar unaposicion).

Para crear un vector: a = vector(cx, cy, cz),siendo cx, su componente x, etc. Para acceder a lascomponentes se usa a.x, a.y, a.z.

Operaciones con vectores 3DPara sumar dos vectores se usa el operador +:a = vector(1,2,3)

b = vector(4,5,6)

c=a+b

Si se imprime c se muestra un vector concomponentes (5, 7, 9).

Asimismo, se puede usar un vector para usarlo comoposicion, como en el ejemplo anterior:bola=sphere(pos=vector(4,7,3),

radius=5,color=color.green)

Dibujo de otros elementosSe pueden dibujar otros objetos como cilindros(cylinder), conos (cone), flechas (arrow), etiquetasde texto (label), curvas (curve), etc.

Se pueden dar texturas de materiales (materials),por ejemplo de plastico:bola=sphere(pos=vector(4,7,3), radius=5,

material=materials.plastic)

Animacion en 3D de una bola roja en un suelo azul

from visual import *

suelo = box(pos=(0,0,0), length=4, height=0.5,

width=4, color=color.blue)

bola = sphere(pos=(0,4,0), radius=1, material=materials.wood)

bola.velocidad = vector(0,-1,0)

dt = 0.01

while 1:

rate(100) # ‘frames’ por segundo

bola.pos = bola.pos + bola.velocidad*dt

if bola.y < bola.radius:

bola.velocidad.y = abs(bola.velocidad.y)

else:

bola.velocidad.y = bola.velocidad.y-9.8*dt

Salida grafica del ejemplo

Red cristalina del Fe-αEl hierro α forma cristales cubicos centrados enel cuerpo de 28.8 nm. Realice una representaciongrafica de una celda de hierro α, suponiendo que elradio de cada atomo es de 4 nm (el real, de 0.14 nmes demasiado pequeno en la visualizacion).

Dibujaremos cada atomo de Fe de color azul en susposiciones correspondientes.

Red cristalina del Fe-α# -*- coding: utf-8 -*-

from visual import *

d, r = 28.8, 4

# vertices del cubo

xv, yv, zv = [0, d], [0, d], [0, d]

# centro del cubo

xc, yc, zc = 0.5*d, 0.5*d, 0.5*d

sphere(pos=(xc,yc,zc), radius=r, color=color.blue)

for x in xv:

for y in yv:

for z in zv:

sphere(pos=(x,y,z), radius=r, color=color.blue)

Salida grafica del ejemplo

Problema 4El cristal de NaCl (sal comun) tiene una estructuracubica centrada en las caras (busquese la forma delcristal en Internet).

La constante de la red (lado del cubo) es a =564 pm. El radio del ion sodio es rNa+ = 116 pmy el radio del ion cloruro es rCl− = 167 pm.

Dibuje una celda del cristal de NaCl, con los ionessodio de color naranja y los iones cloruro de colorazul.

Salida grafica del problema

Indice general

Manejo de vectores y matrices con numpy

Representaciones graficas en 2D y 3D

Creacion de escenas realistas en 3D

Calculo numerico y cientıfico con scipy

Comparacion entre Python y Octave/Matlab R©

Calculo numerico y cientıficocon scipy

Se usa scipy de la siguiente manera (por ejemplo):from scipy import *

La mayorıa de las funciones asociadas a scipy queveamos poseen mas argumentos opcionales que losindicados. Para mas informacion debe consultarse:http://docs.scipy.org/doc/

Usando scipy

scipy usa internamente numpy, y algunas de lasfunciones estan disponibles directamente (como porejemplo poly1d para manejar polinomios).

Sin embargo algunos modulos definidos en numpy

(como linalg) no estan exportados.

Es conveniente por tanto importar de esta manera:>>> from numpy import *>>> from scipy import *

Modulos de calculo numerico 1/2

Solo expondremos algunos modulos y dentro de ellosalgunas funciones.

Estos ya estan ya en numpy:

linalg algebra lineal.random numeros (pseudo)aleatorios.poly1d manejo de polinomios.fft transformada rapida de Fourier.

Modulos de calculo numerico 2/2

Estos otros estan definidos en scipy:

special funciones especiales.stats funciones estadısticas.interpolate interpolacion.optimize optimizacion y busqueda de raıces.integrate integracion y ecuaciones diferenciales

ordinarias.

Funciones de algebra lineal 1/4El submodulo linalg contiene diversas funciones dealgebra lineal, que trabajan en 2D (algunas tambienen 1D). Solo comentaremos algunas de ellas:

linalg.inv(a) calcula la inversa matricial del arraya, que debe ser cuadrado y no singular.

linalg.pinv(a) calcula la pseudo-inversa del arraya, que no necesita ser cuadrado. Si a es cuadradoentonces inv y pinv devuelven la misma solucion.

Funciones de algebra lineal 2/4linalg.matrix rank(a) calcula el rango del arraya.

linalg.det(a) calcula el determinante del arraycuadrado a.

linalg.norm(a, ord=None) calcula la norma delarray a (por defecto la norma de Frobenius o L2).

linalg.cond(a, p=None) calcula el numero decondicion del array a (por defecto la norma L2).

Funciones de algebra lineal 3/4linalg.cholesky(a) realiza la descomposicion deCholesky del array cuadrado a considerado comomatriz.

linalg.svd(a) realiza la descomposicion de valoressingulares del array a considerado como matriz.

linalg.eig(a) calcula los autovalores y autovectoresdel array cuadrado a considerado como matriz.Devuelve dos arrays, el primero con los autovaloresy el segundo con los autovectores.

Funciones de algebra lineal 4/4linalg.solve(a, b) resuelve el sistema a x = b.El array a ha de ser cuadrado y no singular. Si atiene por dimensiones (m, n) entonces b ha de tenerdimensiones (m,) o (m, n).

linalg.lstsq(a, b) retorna la solucion delsistema a x = b obtenida minimizando la normaeuclıdea ||b− ax||2.

Numeros aleatoriosUn numero aleatorio es un numero obtenido por azar,pero no de cualquier manera sino siguiendo una ley

de probabilidades (ley de densidad).

Un caso facil de entender es el de un dado de 6 caras:se pueden obtener los numeros 1, 2, 3, 4, 5 y 6.Se tiene entonces una variable aleatoria discreta, quepuede tomar los valores 1, 2, 3, 4, 5 y 6.

Variables aleatorias discretasTirar un dado es hacer una realizacion de la variablealeatoria: sale uno de esos numeros. Si el dado noesta cargado existe igual probabilidad de que salgacualquier numero de 1 a 6, que sera diferente a cadatirada debido al azar. f es la ley de densidad.

1 2 6 x3 4 5

f

1

6

Variables aleatorias continuasSe puede extender la definicion a variables continuas,con distribuciones de probabilidad continuas. En esecaso se trabaja con areas entre dos puntos del eje Ox:

P =∫ b

af(x)dx es la

probabilidad de que unnumero tomado al azarsegun la distribucion fcaiga entre a y b. a xb

f

P

La distribucion uniformeEn la practica existe una distribucion basica: ladistribucion uniforme entre 0 y 1, etiquetada U(0, 1),que tiene por funcion de densidad:

f(x) =

{

1 0 ≤ x < 10 x < 0, x ≥ 1

0.0 x1.0

f

1

Mediante transformaciones de variable aleatoria esposible generar cualquier otra distribucion.

La distribucion normal o gaussiana

Tiene por funcion de densidad:

f(x, µ, σ) =1

σ√2π

exp

(

−(x− µ)2

2σ2

)

µ es la media de la distribucion y σ su desviaciontıpica. La variable aleatoria x puede tomar cualquiervalor entre −∞ y +∞ pero es mas probableencontrar las x cercanas a µ.

Generando numeros aleatorios 1/3

La generacion de numeros estrictamente aleatorioses imposible en un ordenador. Nos vale con numerosque sean “suficientemente” aleatorios (denominadospseudoaleatorios).

Se genera una secuencia de numeros a partir de unoinicial conocido, x0, que se denomina semilla:

xn+1 = G(xn).

La funcion G debe ser elegida cuidadosamente.

Generando numeros aleatorios 2/3

Se suelen generar numeros aleatorios enterospositivos entre 0 y un lımite Imax (que depende delnumero de bits usados).

Se combinan diversos metodos. Uno sencillo,denominado de las congruencias, usa la formula:

In+1 = (aIn + b) mod m,

siendo a, b y m enteros bien elegidos, partiendo deuna semilla conocida I0.

Generando numeros aleatorios 3/3

Posteriormente se obtiene un numero real U(0, 1)haciendo:

xn+1 =In+1

Imax

Numeros aleatorios distribuidos de otra manera seobtienen a base de numeros U(0, 1), por lo que ungenerador uniforme es la base de todos los demas.

Un buen generador tiene un perıodo Imax, al cabo delcual se repiten la secuencia.

El generador de aleatorios denumpy

Es un generador del tipo “Mersenne Twister” con unperıodo de 219937 − 1 ≈ 106002.

Si se llama al generador 109 veces por segundo, alcabo de un ano se habran generado 3×1016 numeros,muy lejos de agotarse la secuencia.

Para mas informacion vease:http://en.wikipedia.org/wiki/Mersenne twister

La eleccion de la semillaEn muchos casos nos interesa una semilla lo masaleatoria posible. En ese caso se toma un numeroentero generado a partir del reloj interno delordenador.

En otras ocasiones nos interesa una semillaintroducida a mano. Por ejemplo, cuando estamosprobando un nuevo metodo para resolver un problemapor el metodo de Montecarlo conviene que losresultados de nuestro programa sean reproducibles.

Manejo de la semillaLa funcion random.seed(semilla) nos permiteinicializar el generador de aleatorios. La semilla esun numero entero (o un array de enteros) a partir delcual se empiezan a generar numeros aleatorios:>>> random.seed(200); print(random.rand(2))

[ 0.94763226 0.22654742]

>>> random.seed(200); print(random.rand(2))

[ 0.94763226 0.22654742]

Si no se especifica la semilla se usa tıpicamente elreloj del ordenador (o /dev/urandom si existe en elordenador).

Arrays aleatorios: funciones simples

random.rand(shape) devuelve un array con laforma dada relleno de numeros U(0, 1).

random.randn(shape) devuelve un array con laforma dada relleno de numeros N(0, 1).

random.normal(m, s, shape) devuelve un arraycon la forma dada relleno de numeros N(m, s).

random.uniform(a, b, shape) devuelve un arraycon la forma dada relleno de numeros U(a, b).

Arrays aleatorios: distribucionesrandom.binomial(n, p) binomial.

random.chisquare(df) chi cuadrado.

random.poisson(lam) poisson.

random.lognormal(mean, sigma) lognormal.

random.standard t(df) t de Student.

random.f(dfnum, dfden) F de Fisher-Snedecor.

Polinomios 1/2numpy tiene dos maneras de manejar polinomios.

Aquı veremos la mas sencila, que utiliza la funcionpoly1d para crear polinomios a partir de arrays olistas numericas (el elemento 0 es el coeficiente demayor orden):

>>> p = poly1d([3, 4, 5])

crea una variable p que codifica el polinomio

3x2 + 4x+ 5

Polinomios 2/2Se puede obtener el array de sus coeficientes:>>> p.c

array([ 3, 4, 5])

El orden (o grado) del polinomio se obtiene ası:>>> p.order

2

Operaciones con polinomiosCon los polinomios se puede operar de la manerausual:>>> q = p*p

>>> print(q)

4 3 29 x + 24 x + 46 x + 40 x + 25

>>> q+p

poly1d([ 9, 24, 49, 44, 30])

>>> r = poly1d([3,7,6,2])

>>> r/p # devuelve cociente y resto

(poly1d([ 1., 1.]), poly1d([-3., -3.]))

Valores, derivada e integralSe puede calcular su valor en un punto o en varios:>>> (p**3)(1) # calcula p3 en x = 11728

>>> p([2, 3]) # en x = 2 y x = 3array([25, 44])

y derivarlos e integralos:>>> p.deriv()

poly1d([6, 4])

>>> p.integ(k=4) # k: cons. de integracion

poly1d([ 1., 2., 5., 4.])

Raıces de polinomiosTambien se pueden calcular sus raıces:>>> print(p.r)

[-0.66666667+1.1055416j -0.66666667-1.1055416j]

que como vemos son complejas).

Tambien se puede obtener el polynomio a partir desus raıces:>>> p1 = poly1d([1, 2], True)

poly1d([ 1, -3, 2])

Ajuste de polinomios a datosSe puede obtener el polinomio p(x) que minimiza

E =k−1∑

i=0

[p(xi, m)− yi]2

siendo m el orden del polinomio y k el numero depuntos, x e y dos vectores, mediante polyfit:>>> x = array([0.0, 1.0, 2.0, 3.0, 4.0])>>> y = array([0.0, 0.8, 0.9, 0.1, -0.8])>>> polyfit(x, y, 2) # orden 2array([-0.30714286, 0.99857143, 0.04571429])

Transformada rapida de Fourier

Es una transformada discreta. Solo la comentaremos.Dado un array b, de longitud n, se define latrasnformada 1D discreta de Fourier, como el array Ade longitud n cuyos coeficientes son:

Ak =

n−1∑

m=0

bm exp

(

−2πjmk

n

)

, k = 0, 1, . . . , n−1,

siendo j la unidad imaginaria. La transformadainversa se calcula de la misma manera pero dividiendopor n antes del sumatorio.

El modulo fft

Dentro del modulo fftg, numpy posee variasfunciones para tratar la transformada de Fourier. Labasica es fft y su inversa, ifft:>>> x = array([0.0, 1.0, 2.0, 3.0, 4.0])

>>> A = fft.fft(x)>>> Aarray([ 10.0+0.j , -2.5+3.4409548j ,

-2.5+0.81229924j,-2.5-0.81229924j, -2.5-3.4409548j ])

>>> fft.ifft(A) # transformada inversa

array([ 0.+0.j, 1.+0.j, 2.+0.j,3.+0.j, 4.+0.j])

Funciones especiales 1/2El modulo special incluye numerosas funcionesespeciales de la fısica-matematica: de airy, elıpticas,de bessel, gamma, beta, hipergeometricas, etc.

Por ejemplo, para usar gamma y beta de Euler seinvocarıa ası:>>> from scipy.special import gamma, beta

La mayorıa siguen las mismas reglas de broadcasting

que las funciones matematicas usuales (como sin):se pueden usar como ufuncs.

Funciones especiales 2/2Ejemplos:>>> print(gamma(6)) # 5!120.0>>> print(beta(3, 6))0.00595238095238# ahora la funcion de Bessel Jn(x)>>> from scipy.special import jn>>> import matplotlib.pyplot as plt>>> x = linspace(0, 20, 100)>>> plt.plot(x, jn(0, x), label = "J0")>>> plt.plot(x, jn(1, x), label = "J1")>>> plt.legend(); plt.show()

Salida grafica del ejemplo

0 5 10 15 20

0.5

0.0

0.5

1.0

Funci�n de Bessel J_n(x)

J0J1

Funciones estadısticas 1/2El modulo stats incluye numerosas funcionesestadısticas.

Muchas de esas funciones calculan estadısticos (lamedia, mediana, varianza, kurtosis, etc.). Por ejemplopara calcular la mediana de un array:>>> from scipy.stats import cmedian

>>> a = array([1, 2, 43, 65, 7, 8])

>>> cmedian(a)

7.0540540540540544

Funciones estadısticas 2/2stats tambien se proporcionan funciones dedensidad y de distribucion (integrales de las funcionesde densidad), discretas y continuas.

Por ejemplo, para usar la normal se invocarıa ası:>>> from scipy.stats import norm>>> x = array([1, 2, 3])>>> print(norm.pdf(x)) # funcion de densidad[ 0.24197072 0.05399097 0.00443185]>>> print(norm.cdf(x)) # fun. de distribucion[ 0.84134475 0.97724987 0.9986501 ]

Interpolacion 1/3Si se tiene definida una funcion continua en ciertospuntos de un mallado discreto, interpolar es obtenerun valor aproximado al valor real de la funcion enpuntos intermedios de los dados.

Si el punto del que se quiere conocer la ordenadaesta fuera del rango de puntos dados el proceso sedenomina extrapolar (y no es recomendable debido aque las imprecisiones son mayores).

Interpolacion 2/3

x

y

interpolacióncúbica

lineal

cuadrática

extrapolación

Interpolacion 3/3Existen muchas maneras de interpolar. Solotrataremos solo la interpolacion polinomica, incluidaen el modulo interpolate.

Comentaremos la interpolacion en 1D, aunque esemodulo tambien contiene metodos para interpolacion2D.

Hablaremos de interp1d y de splines

Usando interp1d 1/3Esta funcion crea otra funcion que permite serinvocada en puntos en el interior del rango deinterpolacion: x ∈ [xmin, xmax].

Se puede indicar que tipo de polinomio interpolanteusamos: lineal, cuadratico, cubico y otros.

A priori, cuanto mayor sea el orden del polinomio masprecisa es la interpolacion.

Usando interp1d 2/3Se invoca ası:

f = interp1d(x, y, kind=’modo’)

siendo por defecto el modo linear (otros usualesson kind=’quadratic’ y kind=’cubic’).

En ese caso f es una funcion de una variable x quepuede usarse como funcion universal sobre un array.

Veamos un ejemplo.

Usando interp1d 3/3 # -*-

coding: utf-8 -*-from numpy import *from scipy.interpolate import *import matplotlib.pyplot as pltx = linspace(0, 10, 10)y = exp(-x/3.0)f = interp1d(x, y) # por defecto kind=’linear’f3 = interp1d(x, y, kind=’cubic’)xnew = linspace(0, 10, 40)plt.plot(x,y,’o’, xnew,f(xnew),’-’,

xnew,f3(xnew),’--’)plt.legend([’datos’,’lineal’,u’cubica’])plt.show()

0 2 4 6 8 100.0

0.2

0.4

0.6

0.8

1.0

1.2datoslinealc�bica

Interpolacion con polinomios atrozos 1/3Los splines son polinomios a trozos que se hacencontinuos en ciertos puntos (que pueden coincidir ono con los los que se dan como datos) denominadosnodos.

Los splines mas tıpicos son los cubicos.

Para usar los splines hay que preparar los polinomiosy luego usarlos.

Interpolacion con polinomios atrozos 2/3Para prepara la interpolacion se usa, por ejemplo,la funcion splrep (tiene mas opciones que lasindicadas):

tck = splrep(x, y, k=3, s=None)

donde x e y son dos arrays con las abscisas y lasordenadas, k es el orden del polinomio (entre 1 y 5),por defecto 3, y s (numero real no negativo) esuna condicion de suavizado (cuanto mas pequeno s

menos suavizado).

Interpolacion con polinomios atrozos 3/3Una vez preparada la interpolacion se usa splev paraevaluar la interpolacion (o una de sus derivadas) enunas abscisas dadas:splev(xnew, tck, der=0)

donde xnew es un arrays con las abscisas de lospuntos en los que se quiere interpolar, tck es lo quedevuelve splrep, y der es el orden de la polinomiodel que se quiere la derivada (k=0, por defecto, y secalcula la funcion y no la derivada).

Ejemplo de interpolacion consplines# -*- coding: utf-8 -*-from numpy import *from scipy.interpolate import *import matplotlib.pyplot as pltx = arange(0, 2*pi+pi/4, 2*pi/8); y = sin(x)tck = splrep(x, y, s=0)xnew = arange(0, 2*pi, pi/50)ynew = splev(xnew, tck, der=0)plt.plot(x,y,’o’, xnew,ynew, ’-’,

xnew,sin(xnew),’b’)plt.legend([’datos’,u’spline cubico’, ’real’])plt.show()

0 1 2 3 4 5 6 7�1.0

�0.5

0.0

0.5

1.0datosspline c�bicoreal

(La diferencia entre el spline y la funcion verdaderaes inapreciable en este grafico.)

Derivadas e integrales medianteinterpolacion con polinomios atrozosSe puede calcular, como vimos, una derivada de lafuncion a interpolar (indicando der=orden):print(splev(array([0, 1, 2]),tck,der=1))[ 1.05922424 0.53317418 -0.41657687]

y tambien su integral, mediante:integral = splint(a, b, tck)

por ejemplo:print(splint(0, pi/2, tck))1.00227987749

Raices mediante interpolacioncon polinomios a trozosCuando se tienen mas de 8 puntos en el spline sepueden calcular tambien las raices (aproximadas) dela funcion interpolada mediante:>>> zeros = sproot(tck)>>> print(zeros)[ 2.40429819e-19 3.14159265e+00]

Optimizacion y busqueda deraıcesEl modulo optimize contiene funciones paraoptimizacion (maximizacion y minimizacion defunciones) y para la busqueda de raıces.

Comentaremos solo algunas funciones interesantes.Para mas informacion vease el manual de referenciade scipy.

Busqueda de raıces 1/5En el caso unidimensional se trata de resolver elproblema matematico:

obtenga x∗ tal que f(x∗) = 0.

Este problema es bastante complejo en general, puesf es generica. Se suele dar un intervalo de busquedao un valor inicial aproximado de la raız.

Busqueda de raıces 2/5

x

f

y

xx*0

Busqueda de raıces 3/5La funcion de scipy para obtener una raiz (de variasposibles en un intervalo) es fsolve. Para obteneruna raız de x + 2 cosx = 0 cercana a x0 = 0.3 seusarıa:>>> from scipy import *

>>> from scipy.optimize import fsolve

>>> def f (x): return x+2*cos(x)

>>> x = fsolve(f, 0.3)

>>> x

-1.0298665293222591

Busqueda de raıces 4/5Si la funcion tiene mas de un argumento fijo, sepueden pasar como una tupla a fsolve. Por ejemplo,si se trata de resolver x+b cos x−a = 0 para diversosvalores de a y b se usarıa:>>> from scipy import *>>> from scipy.optimize import fsolve>>> def g (x, a, b): return x+b*cos(x)-a>>> for a,b in [[0, 2],[0.1, 2.1],[0.2, 2.2]]:>>> . . . x = fsolve(g, 0.3, args=(a,b))>>> . . . print(x)-1.02986652932-1.01248495645-0.996021250293

Busqueda de raıces 5/5Tambien se pueden buscar raıces de funciones devarias variables. Cerca de (1, 1), por ejemplo:

x0 cosx1 = 4, x0x1 − x1 = 5,

serıa:>>> from scipy import *>>> from scipy.optimize import fsolve>>> def ff (x):>>> . . . return [x[0]*cos(x[1])-4,

x[0]*x[1]-x[1]-5]>>> print(fsolve(ff, [1, 1]))[ 6.50409711 0.90841421]

Optimizacion 1/5En el caso unidimensional se trata de resolver elproblema matematico:

obtenga x∗ tal que f(x∗) mınimo.

Este problema es bastante complejo en general, puesf es generica. Se suele dar un intervalo de busquedao un valor inicial aproximado de la raız.

Maximizar f es equivalente a minimizar −f , por loque no suele proporcionarse funcion para maximizar.

Optimizacion 2/5

x

f

y

xx*0

Optimizacion 3/5Dentro del modulo optimize existen diversasfunciones para minimizar, de las que destacamos:

En 1D con un intervalo de busqueda de la posiciondel mınimo fminbound.

En varias dimensiones con un valor inicial aproximadode la posicion del mınimo fmin.

Optimizacion 4/5La funcion fminbound permite minimizar en 1Ddando lımites de busqueda:>>> from scipy import *

>>> from scipy.optimize import fminbound

>>> def g (x): return -x**3+2*sin(x)

>>> x = fminbound(g, -4, 4, xtol=1.0e-10)

>>> print(x)

[-0.71079469]

Como vemos, se puede dar una tolerancia opcional(por defecto es 10−5) en el error admisible de laabscisa.

Optimizacion 5/5La funcion fmin permite minimizar en variasdimensiones dando un valor inicial, x0, para empezara buscar el mınimo:from numpy import *from scipy.optimize import fmindef g (x):return exp(-0.1*x[0])*sin(x[0])*cos(x[1]+1.0)

x0 = [1, 1]xopt = fmin(g, x0, xtol=1.0e-8)print(xopt)... # (varias lıneas de informacion)[ 1.47112768 2.14159265]

Ajustes no linealesEn el caso 1D, dada la funcion

y = f(x, ~p),

se trata de buscar el conjunto de parametrosajustables:

~p = (p0, p1, . . .),

que mejor se ajuste a un conjunto de k puntos(xi, yi), i = 0, 1, . . . , k − 1.

Metodo de mınimos cuadradosSe suele utilizar como criterio de ajuste: buscar ~p queminimice E.

E =

k−1∑

i=0

e2i

=

k−1∑

i=0

[yi − f(xi, ~p)]2

y

x

xi

yi

( , )

e i

f

Mınimos cuadrados en scipy

La funcion mas interesante es curve fit, que realizael ajuste por el metodo de Levenberg–Marquardt. Sepuede usar de la siguiente manera:

curve fit(f, x, y, p0)

Si no se proporciona p0 se toma un valor inicial debusqueda p0 = [1, 1, . . .].

Usando curve fit

from numpy import *import matplotlib.pyplot as pltimport scipy.curve fit as curve fitx = array([50., 110., 170., 230., 290.])y = array([3173., 2391., 1726., 1388., 1057.])xdib = linspace(x[0], x[-1], 20)def f (t, a, b, c): return a*exp(b*t)+cp, cov = curve fit(f, x, y, p0=[4e3,-0.005,99])lc = ’y = %.0f exp( %.4f x)+ %.0f’ % tuple(p)plt.xlabel(’x’); plt.ylabel(’y’)plt.plot(x, y, ’ro’, xdib, f(xdib, *p))plt.legend([’puntos’, lc])plt.show()

50 100 150 200 250 300x

1000

1500

2000

2500

3000

3500y

puntosy = 3780 exp(-0.0057 x)+335

IntegracionEl modulo integrate contiene rutinas para realizarintegrales definidas (cuadraturas) y para resolversistemas de ecuaciones diferenciales ordinarias(SEDO).

Comentaremos solo unas pocas rutinas: quad pararealizar cuadraturas en 1D, e integracion de SEDOcon odeint.

Cuadraturas en 1DEn 1D la funcion mas general es quad, que nos realizala integracion de una funcion de una variable entredos lımites.

Se invoca (hay mas argumentos opcionales):

quad(f, a, b, epsabs=valor)

siendo f la funcion a integrar, a y b los lımites deintegracion (que pueden ser ±∞), y epsabs el errorabsoluto admisible en la integracion (por defecto1.5e-8).

Ejemplo de cuadratura en unadimensionLa fuerza por unidad de altura en N m−1 sobre elmastil de un barco de vela viene dada por:

F (z) = 200

(

z

2 + z

)

exp(−z/5),

viniendo expresada la altura respecto al suelo enmetros. Determine la fuerza total ejercida sobre elmastil si tiene 10 m.

Solucionfrom numpy import * # para exp()

from scipy.integrate import quad

def f (z):

return 200.0*z/(2.0+z)*exp(-z/5.0)

F = quad(f, 0.0, 10.0, epsabs=1.0e-6)

print(F)

# (resultado, error aproximado actual)

(462.50466684953761, 4.2931842087556273e-09)

Integracion de SEDOSe resuelve el problema de condiciones inicialessiguiente. Dado el sistema:

dy0dt

= f0(y0, y1, . . . , t),

dy1dt

= f1(y0, y1, . . . , t),

. . .dyn−1

dt= fn−1(y0, y1, . . . , t),

y conocidas yi(t = 0) = y0i , determinar yi(t) paradiversos valores de t.

La rutina odeint

odeint es la funcion generica para integrar SEDOque proporciona scipy.

Se invoca de la siguiente manera:

odeint(fun, y0, t, args)

siendo fun(y, t) la funcion que define el SEDO, y0los valores iniciales y t un array con una secuenciade valores en los que se quiere la solucion. args sonargumentos opcionales que se pasan (si se desea) afun.

Ejemplo de integracion de SEDOEl oscilador de Van der Pol es un oscilador noarmonico, que verifica:

v =dy

dt, a =

dv

dt= µ(1− y2)v − y.

µ es un parametro (µ = 0 implica osciladorarmonico).

Obtenga la posicion y de la partıcula en el osciladorde Van der Pool para el caso µ = 1, y(0) = v(0) = 1,comparandola con el caso armonico.

Solucionfrom numpy import *from scipy.integrate import odeintimport matplotlib.pyplot as pltdef f (y, t, mu): # Van der Polreturn array([y[1], mu*(1-y[0]**2)*y[1]-y[0]])def g (y, t): # armonicoreturn array([y[1], -y[0]])t = linspace(0, 20, 201)y = odeint(f, [1,1], t, args=(1,))ya = odeint(g, [1,1], t)plt.xlabel(’t’); plt.ylabel(’y’)plt.plot(t,y[:,0], t, ya[:,0], ’r’)plt.legend([’Van der Pool’, u’armonico’])plt.show()

0 5 10 15 20t

�3

�2

�1

0

1

2

3y

Van der Poolarm�nico

Indice general

Manejo de vectores y matrices con numpy

Representaciones graficas en 2D y 3D

Creacion de escenas realistas en 3D

Calculo numerico y cientıfico con scipy

Comparacion entre Python y Octave/Matlab R©

Comparacion entre Python yOctave/Matlab R©

Octave (version libre de Matlab R©) y numpy/scipy

tienen mucho en comun, pero existen bastantesdiferencias.

numpy/scipy fueron creados para realizar calculosnumericos y cientıficos de la manera mas integradoraposible dentro de Python.

numpy/scipy no son clones de Matlab R©.

Algunas cuestiones importantes 1/4

Tanto en Matlab R© como en numpy el tipo basicode datos es el array multidimensional. Sin embargo,Matlab R© tiene operaciones especiales para trabajarelemento a elemento, y las funciones normales sonpara trabajar como en algebra lineal. En numpy lasoperaciones normales con arrays son elemento aelemento.

Matlab R© usa indexado comenzando en 1 y acabadoen n, mientras que numpy comienza los arrays en 0 yllegan hasta n-1.

Algunas cuestiones importantes 2/4

En Matlab R© los arrays se pasan a las funcionespor valor, con un sistema que copia los arraysen los parametros cuando es realmente necesario.Las operaciones con secciones (slices) en Matlab R©

copian partes de arrays.

numpy pasa los arrays por referencia (solo pasa ladireccion de memoria donde estan los datos) y sepueden modificar los arrays dentro de una funcion.Las operaciones con secciones devuelven vistas delos arrays.

Algunas cuestiones importantes 3/4

En Matlab R© cada funcion debe estar en un ficherocon el mismo nombre (y acabado en .m), y nose pueden definir funciones locales en un programaprincipal.

numpy es Python puro, por lo que no tienerestricciones: se pueden definir funciones como sedesee y en el lugar que quiera. Ademas se puedenusar las herramientas de programacion orientada aobjetos de Python.

Algunas cuestiones importantes 4/4

Matlab R© proporciona un entorno de trabajocompleto, con ventanas interactivas, editor integradoy depurador.

numpy no posee esas funcionalidades, pero existendiversas herramientas para Python que suplen enparte esas funciones citadas.

Software libre frente a softwarepropietarioMatlab R© es de pago (puede llegar a varios miles deeuros) y el codigo fuente no esta disponible. Octavees libre y permite la misma sintaxis que Matlab R© perono tiene la misma calidad.

numpy es totalmente libre y se dispone del codigofuente si se necesita.

Mas informacionVeanse:

http://www.scipy.org/NumPy for Matlab Users

http://www.scipy.org/NumPyProConPage

Una tabla comparativa de varias paginas muy utilesta en:

http://www.cert.org/flocon/2011/matlab-python-xref.pdf