<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Notebook para discutir generación y graficación de ondas.
Este tipo de documento se llama cuaderno de notas o notebook y sirve para mezclar documentación y código al mismo tiempo de manera que los dos estén entrelazados. Elegí crear el primer material aquí de manera que quede estructurado como referencia pero que además puedas jugar con él para practicar lo ahí explicado
Celdas
Las celdas son el elemento básico de las notebook. Sus contenidos pueden ser textuales como esta celda y la previa pero también pueden incluir código u otras cosas que tal vez discutiremos en un futuro. 
Programa
A continuación comenzamos con el programa lo primero que hay que hacer para comenzar un programa es llamar a las librerías de trabajo. Las librerías son como una caja con herramientas de trabajo. Diferentes tipos de tareas requieren diferentes tipos de herramientas y la comunidad en consequencia a organizado todas las posibles herramientas en torno a la abstracción de librería. A continuación te hablo sucintamente de las usaremos en esta notebook
Step1:  Notarás por el número a la izquierda (el número 1) que esa celda es diferente. Ese número significa que es el primero output o salida del programa y sirve para diferenciar e identificar las celdas con código entre sí y de las textuales.
Vector de tiempos
Numpy o np que es su alias tienen la capacidad de crear vectores como fue mencionado anteriormente. Sin más preambulos creo el vector aquí y te explico que viene después
Step2:  Los nombres son bastante obvios, la primera cantidad T_init permite iniciar el timepo inicial mientras que Tmax permite controlar hasta donde llegará el vector de tiempos. Finalmente dt permite ajustar el tamaño del salto entre un número y el siguiente. La declaración del vector se hace con la instrucción np.arange (nota que usamos el alias para decir que esta herramientas pertenece a la caja de numpy). 
A continuación otro ejemplo para que des una mejor idea de como funcionan los parametros o argumentos de la función
Step3:  Para modificar una celda de programación como la anterior simplemente dale click y puedes modificar las cosas directamente con tu teclado. Cuando quieras ejectura (o correr) el contenido presiona shift y enter al mismo tiempo (shift + enter). En caso de que no necesites algo más en el menú de la notebook está un menú de ayuda con todos los comandos. 
Para asegurarte de que entiendes todo lo que sucede con el vector anterior. Intenta producir un vector que vaya del 10 al 15 con saltos de 0.2. Lo que debeŕia de aparecer una vez que ejecutes la celda es algo como
Step4:  Notarás que la onda se ve bastante mal deformada, si buscas en google una fotografía del seno deberías encontrar que en realidad se debería de ver algo como así
Step5:  Basandonos en esta imagen debería ser notorio que el problema principal es que no tenemos suficientes puntos para cubrir la señal de manera adecuada. Este tipo de observaciones dan pie al tipo de invetigaciones de cuantos puntos concretos son necesarios para recuperar la información de una señal (teoría de la información) y más particularmente el fenomeno de aliasing en el procesamiento de señales. Pero esto es para una futura discusión y simplemente un comentario lateral. 
Volviendo al problema que tenemos a la mano la solución es hacer más pequeños los satlos entre los números para tener más
Step6:  Como ejercicio deberías de modificar los valores de dt y los tiempos iniciales y finales para ver como eso afecta la gráfica. Otra cosa que puedes hacer es leer en google sobre los commandos xlim and ylim y agregarlos al pequeño programa de arriba para ver como afectan la visualización.
Tamaño correcto de las ondas
Finalmente para comenzar a trabajar con distintas frecuencias será necesario ajustar las unidades apropiadas, esto lo discutiremos en persona. 
Supongamos que queremos una onda cuyo frequencia sea 1.0. Es decir un ciclo por unidad, la manera matemática de hacer esto es multiplicar los tiempos por la frequencia adecuada. En el siguiente código nota como los tiempos son multiplicados por la frequencia f  además de esto también multiplicamos por la longitud del circulo para finalmente tener las unidades adecuadas. Más de esto en nuestra discusión en persona.
Step7:  Notarás que la frecuencia es demasiado alta y que por lo tanto no se puede apreciar correctamente, modifiquemos los tiempos finales para ver esto desde otro angulo
<ASSISTANT_TASK:>
Python Code:
import numpy as np    # Alias es np
import matplotlib.pyplot as plt   # Alias es plt
Explanation: Notebook para discutir generación y graficación de ondas.
Este tipo de documento se llama cuaderno de notas o notebook y sirve para mezclar documentación y código al mismo tiempo de manera que los dos estén entrelazados. Elegí crear el primer material aquí de manera que quede estructurado como referencia pero que además puedas jugar con él para practicar lo ahí explicado
Celdas
Las celdas son el elemento básico de las notebook. Sus contenidos pueden ser textuales como esta celda y la previa pero también pueden incluir código u otras cosas que tal vez discutiremos en un futuro. 
Programa
A continuación comenzamos con el programa lo primero que hay que hacer para comenzar un programa es llamar a las librerías de trabajo. Las librerías son como una caja con herramientas de trabajo. Diferentes tipos de tareas requieren diferentes tipos de herramientas y la comunidad en consequencia a organizado todas las posibles herramientas en torno a la abstracción de librería. A continuación te hablo sucintamente de las usaremos en esta notebook:
Numpy: Permite trabajar con vectores, los vectores son grupos de números con las mismas características: (5.0, 3.0, 20) es uno (3.4, 2.3, 1.2, 3.4) es otro ejmplo. Usaremos esta librería para las cantidades.
Matplotlib: Sirve para gráficar, es
decir, es el conjunto de herramientas que convierte información númerica en información visual. Tocaremos esta librearía superficialmente para ver el resultado de las computaciones que aquí desarollemos.
Lo primero que hacemos entonces es importar las dos librerías y además un alias o apodo estandarizado para referirnos a ellas sin escribir tanto. Para ejecutar una celda.
End of explanation
T_init = 0.0  # Tiempo inicial
Tmax = 10.0  # Tiempo Total
dt= 2.0  # Salto
tiempos = np.arange(T_init, Tmax, dt)
print tiempos
Explanation: Notarás por el número a la izquierda (el número 1) que esa celda es diferente. Ese número significa que es el primero output o salida del programa y sirve para diferenciar e identificar las celdas con código entre sí y de las textuales.
Vector de tiempos
Numpy o np que es su alias tienen la capacidad de crear vectores como fue mencionado anteriormente. Sin más preambulos creo el vector aquí y te explico que viene después:
End of explanation
T_init = 2.0  # Tiempo inicial
Tmax = 8.0  # Tiempo Total
dt= 1.0  # Salto
tiempos = np.arange(T_init, Tmax, dt)
print tiempos
Explanation: Los nombres son bastante obvios, la primera cantidad T_init permite iniciar el timepo inicial mientras que Tmax permite controlar hasta donde llegará el vector de tiempos. Finalmente dt permite ajustar el tamaño del salto entre un número y el siguiente. La declaración del vector se hace con la instrucción np.arange (nota que usamos el alias para decir que esta herramientas pertenece a la caja de numpy). 
A continuación otro ejemplo para que des una mejor idea de como funcionan los parametros o argumentos de la función:
End of explanation
%matplotlib inline 
# Esto es para que las gráficas se muestren en patanlla en lugar de una ventana aparte.
T_init = 0.0  # Tiempo inicial
Tmax = 20.0  # Tiempo Total
dt= 1.0  # Salto
tiempos = np.arange(T_init, Tmax, dt)
# El siguiente comando es equivalente a calcular el seno en TODOS los tiempos de arriba.
onda = np.sin(tiempos)  # La onda evaluada en todos los tiempos. sin=seno=sinus
plt.plot(tiempos, onda)  # Muestra en pantalla 
Explanation: Para modificar una celda de programación como la anterior simplemente dale click y puedes modificar las cosas directamente con tu teclado. Cuando quieras ejectura (o correr) el contenido presiona shift y enter al mismo tiempo (shift + enter). En caso de que no necesites algo más en el menú de la notebook está un menú de ayuda con todos los comandos. 
Para asegurarte de que entiendes todo lo que sucede con el vector anterior. Intenta producir un vector que vaya del 10 al 15 con saltos de 0.2. Lo que debeŕia de aparecer una vez que ejecutes la celda es algo como:
(10, 10.2, 10.4 ... y así sucesivamente hasta el 15 o el número más cercano).
Valor de la onda o señal al tiempo 5, 10, 15, o en general t.
Ahora que tenemos un vector de tiempo, es decir un conjunto de valores con los tiempos y podemos manipular nos gustaría saber como se modifica una señal en esos tiempos. La señal que usaremos será el seno que está incluido en la librería de numpy. Primero definamos de nuevo el vector de tiempos y luego directamente evaluaremos el seno en esos
End of explanation
onda = np.sin(tiempos)  # La onda evaluada en todos los tiempos. sin=seno=sinus
plt.plot(tiempos, onda, '*-')  # El astericos indica que queremos los puntos, el guion que los queremos encadenados
Explanation: Notarás que la onda se ve bastante mal deformada, si buscas en google una fotografía del seno deberías encontrar que en realidad se debería de ver algo como así:
Para entender por que se produce esta deformación hay que recordar que en realidad estamos trabajando con puntos. Cada uno de los elementos de nuestro vector tiempos es en realidad un punto. Por otro lado cuando graficamos de esta manera la librearía automaticamente construye lineas entre los puntos, para evitar que la librearía haga eso necesitamos ser explicitos con ella de la siguiente manera:
End of explanation
T_init = 0.0  # Tiempo inicial
Tmax = 20.0  # Tiempo Total
dt= 0.1  # Salto ESTOS SON MÁS PEQUEÑOS AHORA
tiempos = np.arange(T_init, Tmax, dt)
# El siguiente comando es equivalente a calcular el seno en TODOS los tiempos de arriba.
onda = np.sin(tiempos)  # La onda evaluada en todos los tiempos. sin=seno=sinus
plt.plot(tiempos, onda, '*-')  # Muestra en pantalla
Explanation: Basandonos en esta imagen debería ser notorio que el problema principal es que no tenemos suficientes puntos para cubrir la señal de manera adecuada. Este tipo de observaciones dan pie al tipo de invetigaciones de cuantos puntos concretos son necesarios para recuperar la información de una señal (teoría de la información) y más particularmente el fenomeno de aliasing en el procesamiento de señales. Pero esto es para una futura discusión y simplemente un comentario lateral. 
Volviendo al problema que tenemos a la mano la solución es hacer más pequeños los satlos entre los números para tener más
End of explanation
T_init = 0.0  
Tmax = 20.0  
dt= 0.1  
tiempos = np.arange(T_init, Tmax, dt)
f = 1.0 # Frequencia
unidades = 2 * np.pi  # Esta es la longitud del circulo
onda = np.sin(f * unidades * tiempos)  # La onda evaluada en todos los tiempos. sin=seno=sinus
plt.plot(tiempos, onda, '*-')  # Muestra en pantalla
Explanation: Como ejercicio deberías de modificar los valores de dt y los tiempos iniciales y finales para ver como eso afecta la gráfica. Otra cosa que puedes hacer es leer en google sobre los commandos xlim and ylim y agregarlos al pequeño programa de arriba para ver como afectan la visualización.
Tamaño correcto de las ondas
Finalmente para comenzar a trabajar con distintas frecuencias será necesario ajustar las unidades apropiadas, esto lo discutiremos en persona. 
Supongamos que queremos una onda cuyo frequencia sea 1.0. Es decir un ciclo por unidad, la manera matemática de hacer esto es multiplicar los tiempos por la frequencia adecuada. En el siguiente código nota como los tiempos son multiplicados por la frequencia f  además de esto también multiplicamos por la longitud del circulo para finalmente tener las unidades adecuadas. Más de esto en nuestra discusión en persona.
End of explanation
T_init = 0.0  
Tmax = 5.0 
dt= 0.1  
tiempos = np.arange(T_init, Tmax, dt)
f = 1.0 # Frequencia en Hz
unidades = 2 * np.pi  # Esta es la longitud del circulo
onda = np.sin(f * unidades * tiempos)  # La onda evaluada en todos los tiempos. sin=seno=sinus
plt.plot(tiempos, onda, '*-')  # Muestra en pantalla
Explanation: Notarás que la frecuencia es demasiado alta y que por lo tanto no se puede apreciar correctamente, modifiquemos los tiempos finales para ver esto desde otro angulo
End of explanation
<END_TASK>