Dibujando gráficas como si fueran animaciones en Matlab

Manos dibujando
Matlab permite fácilmente crear gráficas; pero ¿qué pasa cuando queremos hacer una animación de esa gráfica? Por ejemplo, ir presentado cómo se produce la trayectoria de un cuerpo en movimiento. Con animaciones esta tipo de gráficas son espectaculares en cualquier presentación. En una entrada anterior trate un poco sobre este tema utilizando fotogramas.

Aquí, presentare ejemplos donde no se crea video.

Ingenuamente podemos usar un código simple, como el siguiente.

figure(1);
for i=1:1000
T(i)=cos(i);
plot(T);
end

Efectivamente, aunque no aprovechamos la ventaja de la preasginación de memoria, la idea es que no es importante la velocidad del cálculo, sino que se cuente con la construcción dinámica de la curva; por ello, el comando plot tiene ir dentro del ciclo for.

Sin embargo, hasta este punto, el código es inútil. Pues la reserva de memoria de los cálculos es independiente y asíncrona de la memoria gráfica. Es decir la gráfica se producirá cuando se cuente con el vector completo.  La solución es insertar un comando que actualice todas las ventanas ese comando es drawnow.

Con todo, nuestro código se puede estar ejecutando muy rápido; por lo que hay que añadir dentro del código una pausa (comando pause) al que se le puede controlar el tiempo de ejecución. Digamos que esperamos .3 segundos por iteración. De tal modo que nos da bastante tiempo para ver con comodidad los resultados, pero esto es útil cuando los cálculos son pocos.

Mi ejemplo de código entonces es:

figure(1);
for i=1:1000
T(i)=cos(i);
plot(T);
drawnow;
pause(0.3)
end

El factor comet

El comando comet es otra opción para darle movimiento a la construcción de nuestras gráficas. Sin embargo, para pocos puntos su ejecución es demasiado rápida para apreciarse. Por lo cual se requieren muchos puntos para poder apreciar la construcción. Una alternativa es disminuir el paso entre punto y punto o aumentar el intervalo del vector a graficar. Lamentablemente, este comando no tiene una opción para controlar la velocidad, y aunque se puede alterar el código original para cambiar la velocidad, no es muy recomendable si estas iniciando el arte de hacer código para Matlab.

Pero si sientes que tu experiencia es suficiente para hacerlo, pues te recomiendo ir a los foros del mismo Matlab Central donde te puedes dar una idea de cómo hacer tal alteración: foro1, foro2


El siguiente video te muestra el código y los resultados que obtengo.



Preguntas para pensar 

1) Sin que se cree un video en que casos particulares es más útil esta opción que la de crear un video en Matlab. Revisa nuestra entrada anterior  sobre la  creación de animaciones.

Ejercicios

1)  Realiza una rutina donde se pueda visualizar al mismo tiempo varias gráfica en un una sola ventana, puedes usar el comando subplot

2) Aplica esta solución para ver la dinámica una gráfica de tres variables (X,Y,Z) que cambia con el tiempo.

Uso de operaciones vectoriales en lugar de ciclos for para aumentar el desempeño de Matlab

Consideremos el siguiente ciclo, reescrito directamente de C o Fortran

dx = pi/30;
nx = 1+ 2*pi/dx;
for i = 1:nx
     x(i) = (i-1) * dx;
     y(i) = sin(3*x(i));
end

Todas las declaraciones anteriores son validas en Matlab, pero son ineficientes en el proceso de crear tanto a x como a y. Recordemos, Matlab localiza memoria para las variables cada vez que se les añade un nuevo miembro. Como ya lo comentamos en anteriormente en una entrada sobre reasignación de memoria RAM.
Entonces el mejor modo de crear los mismos dos vectores x y y es mediante los siguientes comandos:

x = 0: pi/30:2*pi;
y = sin(3*x);

La primera declaración crea al vector x; con 61 elementos que son almacenados en zonas continuas del RAM. La segunda declaración crea una nueva matriz, y, con el mismo número de elementos que x.

Matlab está diseñado para desarrollar eficientemente operaciones de matrices y vectores. Para tomar la ventaja máxima del hardware de la computadora; por tanto debemos utilizar operaciones vectoriales lo más que podamos.

Un ejemplo más sofisticado
A pesar que Matlab ajusta automáticamente el tamaño de una matriz (o vector) es mucho mejor predesignar la memoria de la matriz. La preasignación garantiza que los elementos de la matriz se almacenaran en zonas continuas de la memoria RAM y que sólo se realizara una vez este proceso.

Consideremos este ejemplo (que admito es artificial, pero didáctico) para crear dos vectores x y y:

dx = pi/30;
nx = 1 + 2*pi/dx;
nx2 = nx/2;

for i = 1:nx2
    x(i) = (i-1)*dx;
    y(i) = sin(3*x(i));
end

for i = round(nx2):nx
     x(i) = (i-1)*dx;
     y(i) = sin(5*x(i));
end

Aquí, conocemos desde el principio el tamaño de los vectores x y y. Así que reasignaremos la memoria creando un vector antes de que sus elementos sean individualmente asignados. Por lo común se utilizan las funciones ones y zeros para la reasignación de memoria; por ejemplo, de este modo:

dx = pi/30;
nx = 1 + 2*pi/dx;
nx2 = nx/2;

x = zeros(1,nx); % pre-allocate row-vectors, x
y = zeros(1,nx); % and y

for i = 1:nx2
x(i) = (i-1)*dx;
y(i) = sin(3*x(i));
end

for i = round(nx2):nx
x(i) = (i-1)*dx;
y(i) = sin(5*x(i));
end

Sin embargo, las declaraciones x(i) y y(i) no han tomado ventaja de la vectorización, aunque los elementos de x y y han sido almacenados continuamente en la RAM.

Así que mejoraremos estas declaraciones mediante un poco de vectorización. Por ejemplo, escribiendo:

x = 0:pi/30:2*pi; % vectorized calculation of x
nx = length(x);
nx2 = nx/2;

y = x; % pre-allocate memory for y

for i = 1:nx2
     y(i) = sin(3*x(i));
end

for i = round(nx2):nx
    y(i) = sin(5*x(i));
end

Finalmente, podemos observar que los cálculos de y puede también ser vectorizados. Por ejemplo, de este modo:

x = 0:pi/30:2*pi; % vectorized calculation of x
nx = length(x);
nx2 = nx/2;

y = x; % pre-allocate memory for y

y(1:nx2) = sin(3*x(1:nx2)); % compute first part of y
y(round(nx2):nx) = sin(5*x(round(nx2):nx)); % and the second part


En mi computadora, resulta que el aumento de velocidad fue de aprox. 1.2 veces. Es decir, utilizar los cálculos basados en vectores fue notoria la mejora. Sin embargo, en este ejemplo son pocos los elementos de los vectores. Mientras más grande es la matriz o vector, más significativo será utilizar vectorización en lugar de una reconstrucción de la matriz por medio del ciclo for.

Por cierto, para medir el tiempo de estos ejemplos, los he escrito como rutinas (scripts que los nombre ejemplo_vector.m) y utilice los siguientes comandos para medir el tiempo.

clear; tic; ejemplo_vector; disp( ['se tardo ' num2str(toc) 's.'] );

Y la salida de este ejemplo es la siguiente imagen:


Uso de pre-asignación de memoria en Matlab para aumentar la velocidad de cálculos

Fun home 1
Como en cualquier otra actividad, programar requiere seguir reglas para ser efectivo. Del mismo modo en que deberíamos limpiar nuestro cuarto de vez en cuando; debemos economizar la memoria de la computadora.

Por ello, en esta entrada, platicaré de las bases de la preasignacion de memoria (memory preallocation) en Matlab. La preasignación de memoria es una práctica excelente de programación que SIEMPRE debemos seguir.

¿De qué trata la preasignación de memoria en Matlab?

A diferencia de los otros lenguajes de programación, como C; Matlab “cuida” de la asignación de memoria automáticamente. Así cuando ejecutas un programa, Matlab reserva espacios de memoria para los datos de todas las variables que se utilizan. Y esto se basa en información local, de un modo similar como en el caso de los tipos de datos o el espacio necesario para todos los elementos.  Veamos un ejemplo con código Matlab:

X = 1:100;
Y = cos(X);

En la línea 1, Matlab identifica que X es un vector compuesto de 100 elementos de formato doble. Entonces reserva la memoria necesaria para cuando se emplee.

En la línea 2, Y es del mismo tamaño que X, de modo que Matlab reserva memoria antes de llenar el espacio con la información de la función cos(X).

Una consecuencia de este mecanismo es que CADA VEZ que se le pide a Matlab almacenar un nuevo conjunto de datos, Matlab realiza el proceso de asignar algo de memoria. Por ejemplo:

X = 1:100;
X(101) = 1;

En este ejemplo, X está compuesto inicialmente de 100 elementos; luego cuando se le ordena a Matlab que llene el elemento 101, implícitamente se le pide a Matlab que reasigne algo de memoria para que se pueda incluir el nuevo elemento de X.

¿Por qué tanto alboroto con la preasignación de memoria?

Para todos los datos en una matriz, Matlab requiere un proceso de memoria continua. Como resultado, si el espacio de memoria para el espacio 101 es solicitado; entonces Matlab copia todos los valores originales de X y los coloca en un nuevo sitio donde hay espacio para hasta los 101 elementos.

Veamos un ejemplo más extremo, si X esta hecho 100 mil elementos en lugar de 100, el tamaño de memoria para X es grande y estos grandes espacios de memoria no son tan fáciles de localizar. Es como querer estacionar un autobús turístico en el centro de la ciudad… toma bastante tiempo.

Es especialmente en los ciclos for cuando este proceso de asignación de memoria es notorio. Por ejemplo en esta rutina (script) al que llame ejemplo_memoria0:

for i=1: 100000
Y(i)=cos(i);
end

En este caso, a cada paso en el ciclo for, se le pide a Matlab que añada un elemento a la matriz Y. De hecho, se le pide a Matlab que engrose a Y en memoria a cada paso.

Al principio del proceso, es fácil y rápido; pues Y es pequeño. Pero a medida que progresa el ciclo, Y se hace cada vez más grande, de modo que Matlab debe encontrar espacios de memoria mucho más grandes. Por lo que se vuelve una pesadilla de asignare

La solución es simple: preasignación de memoria

La idea se basa en que tú sabes de antemano cual será el tamaño del vector, por ello se lo debes comunicar a la computadora antes de que entre en el ciclo for. Por ejemplo, la mayoría de las personas utilizan funciones como ones o zeros de este modo:


Y = zeros(100000,1);
for i= 1:100000
   Y(i) = cos(i);
end

En mi computadora viejita y sobre-explotada, la primera versión tarda: 21.6511 s; y utilizando la pre-asignación de memoria tarda en ejecutarse: 0.009333 s. Es decir, estos cambios significaron que: ¡¡~688 VECES AUMENTÓ LA VELOCIDAD DEL CÁLCULO!!


Ahora, se puede aumentar la velocidad un poco más. En lugar de gastar el tiempo llenado con ceros una matriz, se le puede pedir a Matlab que llene solamente el último elemento de un vector. Por ejemplo:

Y (100000) =0;
for i= 1:100000
Y(i) = cos(i);
end

En este último caso, la rutina tardo 0.009074 s. Este ahorro de tiempo es especialmente significativo cuando se construyen diversas matrices de gran tamaño.

Preguntas para pensar:
1) ¿Cuáles otras prácticas de programación se deben emplear para aumentar la eficiencia de nuestros programas?

Ejercicios
1) En la línea de comandos de Matlab, yo utilicé los siguientes comandos para medir el tiempo de ejecución de mi rutina:

clear, tic; ejemplo_memoria0; disp( ['se tardo ' num2str(toc) 's.'] );

a) ¿Qué hace los comandos tic y toc?
b) En este caso, ¿Por qué es necesario transformar un número en cadena de caracteres?
c) Crea una tabla con los tres ejemplos mostrados en esta entrada donde se muestre la diferencia de velocidades en los procesos de cálculo,

Próximos temas de graficación en Matlab, curso 2012


Estos son los próximos temas que veremos en la clase presencial. Empezando por el comando mas sencillo de este tema: plot
Les pido que empiecen a hacer gráficas simples y si pueden los ejercicios de la sig. lista de entradas.
  1. Cómo hacer graficas polares (0009) 
  2. Cómo poner una linea de tendencia en Matlab (0014)
  3. Cómo hacer gráficas de funciones z(x,y) (0011) 
  4. Cómo hacer gráficas parámetricas en el espacio con Matlab (0010) 
  5. Cómo variar los colores en una gráfica 3D (0013)
  6. Cómo hacer la animación de una senoidal en función del tiempo (0012)

Funciones y comparación de cadenas de caracteres

Este es un código que muestra como se pueden comparar cadenas caracteres. Es en respuesta a la duda (que se comento en clase) de un ejercicio para la creación de funciones.

Por favor, prueben la función e interpreten el proceso de trabajo, usen los comando tic toc de Matlab para ver cuanto tiempo tarda en ejecutarse, y si pueden modifiquen para disminuir este tiempo.

Y si tienen dudas, pueden dejar un comentario en esta entrada.

%% Esta fucion permite calcular entre la funcion seno y coseno.

% Acepta escalares y matrices
% Si se escribe mal la palabra se termina el programa

function y = trigos(cadena)
display('¿Qué función deseas usar?'); % estos son mensajes para orientar al usuario
display(' ');
display('Escribe la palabra <> si quieres usar la función coseno.');
display('o escribe la palabra <> si quieres usar la función seno');
palabra = input('Cualquier otra palabra te saca de esta funcion \n','s'); % aqui se almacena la cadena

 if strcmp(palabra, 'coseno') == 1 ; % strcmp compara las cadenas, si son iguales da un valor de 1
         y = cos(cadena);
 elseif strcmp(palabra, 'seno') == 1 ;
         y = sin(cadena);
 else strcmp(palabra, 'coseno') || strcmp(palabra, 'seno') == 0 ; % esta parte permite versatilidad en las salidas nulas
         display('la función no esta declarada. Adios :)'); % se le orienta al usuario que sucede en el programa
 end

% fin de la funcion
%%%

Cómo hacer funciones escalares y vectoriales en Matlab (0017)



Resumen
Mostramos los fundamentos de cómo hacer fuciones en Matlab, las cuales pueden trabajar con escalares, vectores y matrices.

Empleamos la palabra reservada de Matlab function para crear una función

Preguntas para pensar 

1) En que casos es recomendable utilizar funciones en Matlab
2) ¿Se debería escribir primero un guion antes de hacer una función en Matlab?

Ejercicios

1) Escribe un archivo .m de la función, fun_es(x), que calcule la siguiente función:


El argumento debe aceptar tanto un escalar como un vector. Pruebe su función tecleando en la ventana de comandos de Matlab: fun_es(3) y fun_es([1 2 3])

2) Repita la tarea del ejercicio 1) para la función


Denote la función por fun_lg(x).

3) Se supone que el lector ya creó las funciones fun_es y fun_lg de los problemas 1) y 2). Ahora, cree una función f_es(x) que:


pregunte el nombre de la función que se desea evaluar,
 permita al usuario teclear el nombre de la función,
 evalúe la función con el comando de Matlab feval y devuelva los valores funcionales y
se detenga si la fucnion indicada por el usuario no es fun_es ni fun_lg.

Pruebe su f_es calculando fun_es(3) y fun_lg(3).

Tres ejercicios sobre creación de funciones en Matlab

Estos ejercicios son para comprobar nuestro conocimiento en la creación básica de funciones.

1) Escribe un archivo .m de la función, fun_es(x), que calcule la siguiente función:


El argumento debe aceptar tanto un escalar como un vector. Pruebe su función tecleando en la ventana de comandos de Matlab: fun_es(3) y fun_es([1 2 3])

2) Repita la tarea del ejercicio 1) para la función


Denote la función por fun_lg(x).

3) Se supone que el lector ya creó las funciones fun_es y fun_lg de los problemas 1) y 2). Ahora, cree una función f_es(x) que:


pregunte el nombre de la función que se desea evaluar,
 permita al usuario teclear el nombre de la función,
 evalúe la función con el comando de Matlab feval y devuelva los valores funcionales y
se detenga si la fucnion indicada por el usuario no es fun_es ni fun_lg.

Pruebe su f_es calculando fun_es(3) y fun_lg(3).

Cómo poner un cross-hair (cursor de línea) en las figuras de Matlab

Gráfica con tres cursores de linea
Cuando requerimos explorar una gráfica es una gran ayuda contar con un cursor de línea (cross-hair) vertical o horizontal.
graphics.cursorbar, que es un objeto interno de Matlab, es una solución para tener tal aditamento en nuestras gráficas.

Se inicializa el graphics.cursorbar al sustituir un eje (lo que no es muy útil), o graficando una línea (que es más inteligente). Este objeto se puede personalizar utilizando propiedades como BottomMarker, TopMarker, CursorLineColor, CursorLineStyle, CursorLineWidth, TargetMarkerSize, TargetMarkerStyle, ShowText, Orientation, Position (la cual es una propiedad oculta), entre otras.

Ahh!, por supuesto, también están presentes las propiedades regulares (UserData, Visibility, Parent etc.).
Una vez que el cursor de línea es creado, este puede ser movido por medio del cursor del raton, como el código muestra:

%%%% inicia código
x=0:.01:7; y=plot(x,sin(x));
hCursorbar = graphics.cursorbar(y); drawnow
hCursorbar.CursorLineColor = [1,.2,.3]; % default=[0,0,0]='k'
hCursorbar.CursorLineStyle = ':'; % default='-'
hCursorbar.CursorLineWidth = 1; % default=1
hCursorbar.Orientation = 'vertical'; % =default
hCursorbar.TargetMarkerSize = 10; % default=8
hCursorbar.TargetMarkerStyle = 'o'; % default='s' (square)
%%%% fin del código

Ahora bien, en muchas gráficas se puede desear tener dos o más cursores de línea. Por ejemplo una horizontal y otra vertical (x,y), o bien dos verticales (x_1, x_2); esto se puede hacer en base del sig. código:

x=0:.01:7; y=plot(x,sin(x));
hCursorbar1 = graphics.cursorbar(y);
hCursorbar2 = graphics.cursorbar(y);
% ahora a personalizar la apariencia de hCursorbar1 y a hCursorbar2

Preguntas para pensar
1) Menciona dos aplicaciones especificas y concetras donde es importante tener esta aditamento gráfico


Ejercicios
3) Crea un imagen con dos subgráficas donde esten contenidas dos sendos cursores en linea. Es decir en total tendremos cuatro cursores de linea.
4) En una interface de usuario con gráfica introduce estos cursores de linea.

Primeras actividades a realizar antes del 14 de agosto

FOTO:
WWW.SHUTTERSOTCK.COM/THOMAS M PERKINS
Estas son las primeras actividades que deben realizarar antes de la siguiente clase presencial.

Recuerden que estos temas serán parte de la primera evaluación que realizaremos la siguiente semana. En caso tener alguna duda, dejen un comentario en este post.


2. Observen y realicen TODOS los ejercicios de los siguientes posts, que tratan sobre operaciones básicas en Matlab
  1. Cómo escribir operaciones básicas en Matlab (0001)
  2. Cómo escribir fórmulas básicas en Matlab (0002)
  3. Cómo escribir matrices en Matlab (0003)
  4. Matrices como variables en Matlab (0004)
  5. Suma de vectores y matrices en Matlab (0005)
  6. Multiplicación de matrices (0006)
  7. División entrada a entrada y división de matrices en Matlab (0007)

¡Bienvenidos a su blog didáctico de programación en Matlab!

Este blog tiene la intención de apoyarte académicamente en la clase de programación en Matlab. Por ello es importante que realices las actividades online que a partir de este post se incluirán. Además del material adicional que te ayudara en la clase: videos, notas, calificaciones, hojas de cálculo para hacer trabajo colaborativo. Adicionalemte, en este blog encontraras fechas importantes para el curso, notas y otra información importante. Ciertamente, el blog es un medio de comunicación, por lo cual esperamos que tanto en la clase presencial como en este espacio participes con tus recomendaciones a material didáctico extra que puede ayudarnos a dar un mejor curso.
Recuerda el la clase la hacemos todos =) .
Bienvenido al curso y esperamos que aprendas muchas cosas nuevas, útiles y divertidas ^_^ .
Related Posts Plugin for WordPress, Blogger...