import matplotlib.pyplot as plt

"""
Explanation: Matplotlib
Introduccion
Matplotlib es la libreria ejemplar para la visualización de información en Python. Fue creada por John Hunter con la intención de replicar las capacidaddes para graficar de MatLab.
Es una excelente libreria para graficar 2D y 3D así como para generar figuras cientificas
Algunas de las ventajas de Matplotlib son:
* Facil de usar
* Textos y etiquedas modificables
* Control sobre cada elemento de la grafica
* Alta calidad de imagen en el resultado
* Generalmente modificable
Matplotlib nos permite reproducir graficas programaticamente. como recomencion pueden checar la pagina oficial de Matplotlib en http://matplotlib.org/
Instalacion
Necesitamos instalar primeramente matploblib con el siguiente comando
conda install matplotlib

Importar
Importar el modulo matplotlib.pyplot con el nombre plt:
End of explanation
"""


%matplotlib inline

"""
Explanation: Para la visualizar las graficas en linea ocupamos el codigo:
End of explanation
"""


import numpy as np
x = np.linspace(0, 5, 11)
y = x ** 2

x

y

"""
Explanation: Esta linea de codigo solo es necesaria para los cuadernos de jupyter, si estas usando algun otro editor, deberas de usar el comando plt.show() para visualizar la grafica en otra ventana
Ejemplo Basico
Utilizando dos arreglos de numpy, podemos generar una grafica
End of explanation
"""


plt.plot(x, y, 'r') # 'r' es el color rojo
plt.xlabel('Titulo eje X')
plt.ylabel('Titulo eje Y')
plt.title('Titulo de la grafica')
plt.show()

"""
Explanation: Comandos básicos de Matplotlib
Podemos crear una simple grafica de linea utilizando los siguientes comandos
End of explanation
"""


# plt.subplot(nrows, ncols, plot_number)
plt.subplot(1,2,1)
plt.plot(x, y, 'r--') # Opciones de color
plt.subplot(1,2,2)
plt.plot(y, x, 'g*-');

"""
Explanation: Crear varias graficas en el mismo espacio
End of explanation
"""


# Crear Figura (espacio vacio)
fig = plt.figure()

# Agregar ejes
axes = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # izquierda, abajo, ancho, alto (rango de 0 a 1)

# Graficar los ejes
axes.plot(x, y, 'b')
axes.set_xlabel('Etiqueta X ') # Utilizamos set_ al principio de los metodos
axes.set_ylabel('Etiqueta Y')
axes.set_title('Titulo')

"""
Explanation: Matplotlib orientado a objetos
Introduccion al metodo orientado a objetos
El proposito de utilizar un metodo orientado a objeto es generar un objeto figura y de ahi solo mandar llamar los metodos o atributos del objeto. Este metodo es mas efectivo al momento de manipular varias graficas
Comencemos creando la instancia de figura. Posteriormente crearemos los ejes
End of explanation
"""


# Crear espacio en blanco
fig = plt.figure()

axes1 = fig.add_axes([0.1, 0.1, 0.8, 0.8]) # ejes principales
axes2 = fig.add_axes([0.2, 0.5, 0.4, 0.3]) # ejes insertados

# Figura grande eje 1
axes1.plot(x, y, 'b')
axes1.set_xlabel('X_etiqueta_eje1')
axes1.set_ylabel('Y_etiqueta_eje1')
axes1.set_title('Eje 1 Titulo')

# Figura insertada eje 2
axes2.plot(y, x, 'r')
axes2.set_xlabel('X_etiqueta_eje2')
axes2.set_ylabel('Y_etiqueta_eje2')
axes2.set_title('Eje 2 Title');

"""
Explanation: El codigo es un poco mas complicado, pero tiene la ventaja de que tenemos el control de donde colocar las graficas.
End of explanation
"""


# Usamos una sintaxis similar a plt.figure() excepto que utilizamos una tupla para tomar los valores de fig y axes
fig, axes = plt.subplots()

# Utilizamos el objeto axes para agregar las graficas
axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('Titulo');

"""
Explanation: subplots()
El objeto plt.subplots() actuara como un manejador automatico de ejes
Uso basico:
End of explanation
"""


# Espacio vacio de 1 por 2 subplots
fig, axes = plt.subplots(nrows=1, ncols=2)

# Los ejes es un arreglo de ejes donde se puede graficar
axes

"""
Explanation: The esta manera se puede  especificar el numero de filas y columnas a crear al momento de crear el objeto
End of explanation
"""


for ax in axes:
    ax.plot(x, y, 'b')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('Titulo')

# Mostrar el objeto figura
fig

"""
Explanation: Se puede iterar en los ejes
End of explanation
"""


fig, axes = plt.subplots(nrows=1, ncols=2)

for ax in axes:
    ax.plot(x, y, 'g')
    ax.set_xlabel('x')
    ax.set_ylabel('y')
    ax.set_title('title')

fig    
plt.tight_layout()

"""
Explanation: Un error comun en matplotlib es cuando se empalman las graficas y subgraficas, para ello se puede utilizar los metodos fig.tight_layout() o plt.tight_layout() los cuales automaticamentes ajustan las posiciones de los ejes para evitar que estos se empalmen.
End of explanation
"""


fig = plt.figure(figsize=(8,4), dpi=100)

"""
Explanation: Figure size, aspect ratio and DPI
Matplotlib permite el uso de aspect ratio, DPI and figure size para ser especificado al momento de crear el objeto. Podemos utilizar  figsize  y  dpi  comandos
* figsize es una tupla que nos permite determinar el ancho y la altura de la figura en pulgadas
* dpi son los puntos por pulgada (pixel per inch). 
Por ejemplo:
End of explanation
"""


fig, axes = plt.subplots(figsize=(12,3))

axes.plot(x, y, 'r')
axes.set_xlabel('x')
axes.set_ylabel('y')
axes.set_title('Titulo');

"""
Explanation: Estos argumentos se pueden pasar al administrador del layout como una funcion subplots:
End of explanation
"""


fig.savefig("NombreDelArchivo.png")

"""
Explanation: Guardar figuras
Matplotlib puede generar imagenes de alta calidad, incluyendo PNG, JPG, EPS, SVG, PGF and PDF. 
Para guardar la figura en un archivo utilizamos el metodo  savefig en la clase  Figure :
End of explanation
"""


fig.savefig("NombreDelArchivo.png", dpi=200)

"""
Explanation: En este metodo podemos opcionalmente especificar el DPI y seleccionar los diferentes formatos:
End of explanation
"""


ax.set_title("title");

"""
Explanation: Legendas, etiquetas y titulos
Ahora que ya tenemos una idea de lo basico al momento de crear una figura, vamos a ver como podemos decorar nuestras graficas
 Titulos de la figura
Un titulo puede ser agregado a cada eje de la figurapara emplearlo utiliza el metodo  set_title :
End of explanation
"""


ax.set_xlabel("x")
ax.set_ylabel("y");

"""
Explanation: Etiquetas de los ejes 
Igual que con los metodos  set_xlabel  y  set_ylabel  podemos agregar etiquetas para X y Y
End of explanation
"""


fig = plt.figure()

ax = fig.add_axes([0,0,1,1])

ax.plot(x, x**2, label="x**2")
ax.plot(x, x**3, label="x**3")
ax.legend()

"""
Explanation: Legendas
Se puede utilizar el metodo legend para mostrar los elementos de la figura
End of explanation
"""


# Opciones

ax.legend(loc=1) # upper right corner
ax.legend(loc=2) # upper left corner
ax.legend(loc=3) # lower left corner
ax.legend(loc=4) # lower right corner


# La opcion mas comun
ax.legend(loc=0) # Matplotlib decide por default
fig

"""
Explanation: Si deseamos colocar la leyenda a nuestro gusto podemos utilizar los siguientes atributos
End of explanation
"""


# MATLAB Sintaxis
fig, ax = plt.subplots()
ax.plot(x, x**2, 'b.-') # linea azul con puntos
ax.plot(x, x**3, 'g--') # linea verde de lineas

"""
Explanation: Ajustar colores, tipo y tamano de linea
Matplotlib permite modificar a modo los colores el tipo y tamano de linea
Colores con la sintaxis de MatLab
Con matplotlib, podemos definir el color y el tipo de linea mediante la sintaxis de MATLAB, ejemplo 'b' significa  blue, 'g' significa verde, etc.
End of explanation
"""


fig, ax = plt.subplots()

ax.plot(x, x+1, color="blue", alpha=0.5) # medio transparente
ax.plot(x, x+2, color="#8B008B")        # RGB hex code
ax.plot(x, x+3, color="#FF8C00")        # RGB hex code 

"""
Explanation: Colores con el parametro color= parameter
Podemos definir los colores por medio de sus nombres o los codigos RGB hex y opcionalmente proporcionar un valor alpha con los metodos color y alpha. Alpha indica la opacidad.
End of explanation
"""


fig, ax = plt.subplots(figsize=(12,6))

ax.plot(x, x+1, color="red", linewidth=0.25)
ax.plot(x, x+2, color="red", linewidth=0.50)
ax.plot(x, x+3, color="red", linewidth=1.00)
ax.plot(x, x+4, color="red", linewidth=2.00)

# Tipos de linea ‘-‘, ‘–’, ‘-.’, ‘:’, ‘steps’
ax.plot(x, x+5, color="green", lw=3, linestyle='-')
ax.plot(x, x+6, color="green", lw=3, ls='-.')
ax.plot(x, x+7, color="green", lw=3, ls=':')

# configuracion de espacios 
line, = ax.plot(x, x+8, color="black", lw=1.50)
line.set_dashes([5, 10, 15, 10]) # formato: longitud de linea, longitud de espacio

# Simbolos de marcas: marker = '+', 'o', '*', 's', ',', '.', '1', '2', '3', '4', ...
ax.plot(x, x+ 9, color="blue", lw=3, ls='-', marker='+')
ax.plot(x, x+10, color="blue", lw=3, ls='--', marker='o')
ax.plot(x, x+11, color="blue", lw=3, ls='-', marker='s')
ax.plot(x, x+12, color="blue", lw=3, ls='--', marker='1')

# marker size and color
ax.plot(x, x+13, color="purple", lw=1, ls='-', marker='o', markersize=2)
ax.plot(x, x+14, color="purple", lw=1, ls='-', marker='o', markersize=4)
ax.plot(x, x+15, color="purple", lw=1, ls='-', marker='o', markersize=8, markerfacecolor="red")
ax.plot(x, x+16, color="purple", lw=1, ls='-', marker='s', markersize=8, 
        markerfacecolor="yellow", markeredgewidth=3, markeredgecolor="green");

"""
Explanation: Linea y tipos de marcas
Para cambiar el ancho de la linea podemos utilizar el metodo  linewidth  o  lw . El estilo de linea lo podemos modificar con el metodo linestyle  o  ls
End of explanation
"""


fig, axes = plt.subplots(1, 3, figsize=(12, 4))

axes[0].plot(x, x**2, x, x**3)
axes[0].set_title("Rangos por default")

axes[1].plot(x, x**2, x, x**3)
axes[1].axis('tight')
axes[1].set_title("tight axes")

axes[2].plot(x, x**2, x, x**3)
axes[2].set_ylim([0, 60])
axes[2].set_xlim([2, 5])
axes[2].set_title("rangos manipulados");

"""
Explanation: Control sobre como aparecen los ejes
En esta seccion vamos a ver como controlar el tamano y algunas propiedades de una figura de Matplotlib
Plot range
Podemos configurar los rangos de cada uno de los ejes con los metodos set_ylim y set_xlim en el objeto axes, o axis('tight') para un rango automatizado
End of explanation
"""


plt.scatter(x,y)

from random import sample
data = sample(range(1, 1000), 100)
plt.hist(data)

data = [np.random.normal(0, std, 100) for std in range(1, 4)]

# graficas de cuadros
plt.boxplot(data,vert=True,patch_artist=True);   

"""
Explanation: Graficas especiales
Existen diferentes tipos de graficas: Barra, Histogramas, Puntos y más.
End of explanation
"""


