19 de mayo de 2016

48. Ejemplos con MATPLOTLIB. Curvas cónicas, gráficas 3D, animaciones

Curvas cónicas

Dibujar una elipse
Para dibujar una elipse hay que acceder al submódulo patches. En la API de matplotlib, la capa Artist es la encargada de manejar las construcciones de alto nivel, como las figuras los textos y las líneas. Las otras dos son el Renderer y FigureCanvas. Dentro de Artist tenemos los contenedores (axis, axes & figures) y las primitivas (Line2D, text, rectangle, etc.). Los ejes (axis), las gráficas o subplots (axes) y las figuras (figures) son los lugares donde se dibuja todo lo demás, sobre todo en los subplots. (En realidad un subplot es una subclase de axes).
patches
import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(
    patches.Ellipse(
        (0.5, 0.5),   # (x,y)
        0.6,          # width
        0.5,          # height
    )
)

# fig1.savefig('ellipse1.png', dpi=90, bbox_inches='tight')
plt.show()
En el ejemplo, se define primero una figura. Se añade un axe, añadiendo un área subplot, y, además se añade un patch (podríamos traducir por "añadido"). Este patch es del tipo ellipse, y se define por un centro, un ancho y un alto. Para saber más.
Además, comentado, hay un procedimiento para obtener un screenshot en png.
= = =
Dibujar un círculo
import matplotlib.pyplot as plt
import matplotlib.patches as patches

fig1 = plt.figure()
ax1 = fig1.add_subplot(111, aspect='equal')
ax1.add_patch(
    patches.Circle(
        (0.5, 0.5),   # (x,y)
        0.4,          # radius
    )
)
plt.show()
= = =

Gráficas en 3D

Para crear una gráfica en 3D, necesitamos, básicamente, crear una zona axe de 3 dimensiones. Además, debemos añadirla a la figura con el parámetro projection='3d'. Necesitamos importar el objeto Axes3D desde mpl_toolkits.mplot3d
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

plt.show()
= = =
Dibujo una línea en 3D
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
import matplotlib.pyplot as plt

# Tamaño de la letra de la leyenda
mpl.rcParams['legend.fontsize'] = 10

# Inicializo figura
fig = plt.figure()
#  Inicializo AXE . También con ax = fig.gca(projection='3d')
ax = fig.add_subplot(111,projection='3d')

# Creo un array con ángulos. Varias veces 2 PI
theta = np.linspace(-4 * np.pi, 4 * np.pi, 100)
# Creo una serie de puntos en el eje z. En vez de -2, prueba 0
z = np.linspace(-2, 2, 100)
# Según z, un radio distinto. Prueba un radio constante z=1
r = z**2 + 1
# Calculo un ángulo
x = r * np.sin(theta)
y = r * np.cos(theta)
ax.plot(x, y, z, label='parametric curve')
ax.legend()

plt.show()
Cambia ax.plot(...) por ax.scatter(x, y, z, c='r', marker='*', label='parametric curve') ¿Qué ocurre?
= = =
Y una figura en 3D
from mpl_toolkits.mplot3d import Axes3D
from matplotlib import cm
from matplotlib.ticker import LinearLocator, FormatStrFormatter
import matplotlib.pyplot as plt
import numpy as np

fig = plt.figure()
ax = fig.gca(projection='3d')
X = np.arange(-5, 5, 0.25)
Y = np.arange(-5, 5, 0.25)
X, Y = np.meshgrid(X, Y)
R = np.sqrt(X**2 + Y**2)
Z = np.sin(R)
surf = ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=cm.coolwarm,
                       linewidth=0, antialiased=False)
ax.set_zlim(-1.01, 1.01)

ax.zaxis.set_major_locator(LinearLocator(10))
ax.zaxis.set_major_formatter(FormatStrFormatter('%.02f'))

fig.colorbar(surf, shrink=0.5, aspect=5)

plt.show()
 

Animaciones

Animación sencilla
En el programa definimos
  • data; una serie de puntos en el plano aleatorios.
  • l, una línea roja, pero vacía.
  • límites y textos
  • función update_line: define el conjunto de datos de la línea, según num va añadiendo puntos. ¿FuncAnimation va añadiendo 1 cada vez? ¿Cómo llama a num?
  • FuncAnimation: según su referencia, se le pasa la figura, la función, el número de frames, fargs (data y línea), intervalo de refresco 50 ms  y blit = true
# -*- coding: utf-8 -*-

import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation

def update_line(num, data, line):
    line.set_data(data[...,:num])
    return line,

fig1 = plt.figure()

data = np.random.rand(2, 25)
l, = plt.plot([], [], 'r-')
plt.xlim(0, 1)
plt.ylim(0, 1)
plt.xlabel('x')
plt.title('Test de animacion')
line_ani = animation.FuncAnimation(fig1, update_line, 25, fargs=(data, l),
    interval=50, blit=True)
#line_ani.save('lines.mp4')

plt.show()
= = =
  1. Ver el submódulo animation
  2. Ejemplos de animaciones
  3. Otra página de animaciones https://jakevdp.github.io/blog/2012/08/18/matplotlib-animation-tutorial/


1 comentario: