Prácticas de Espacial, a tope!

Espacial maig 13th, 2011

Hola amiguitas del house! (o del reguetón o de iurovishion o lo que sus guste). Después de el disgusto con las prácticas de espacial estaréis pensando… y a mí que más me da si la práctica fisiológica quiere ver lo que responde una neurona o si ha dicho que para la de psicofísica hay que calcular la sumación como una norma euclídea si yo lo que no sé es hacer un bucler! Jorl!

A ver empecemos por el principio y acabemos por el final (como se hace con los buclers). Imaginemos que queremos explorar el campo visual usando unas deltas de Dirac (no sé a qué práctica me suena…). Aunque a Maria Elena ya la tenemos un poco castigada y la vamos a enviar de contertulia a Qué Tiempo Tan Feliz, antes la remataremos un poco. El cloroformo le ha fastidiao las neuronas y su campo visual se ha encogido y ahora es una matriz de 10 x 10.

El experimento va a consistir en hacer una matriz de ceros 10 x 10

receptimetro = zeros(10)

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

E ir poniendo un uno en cada posición. Yo no pienso escribir 100 matrices a mano (y espero que Mariajosé y cía no escriban 4096). Más cómodo va a ser pedirle a Matlá que lo haga él.

En el post anterior os expliqué que los bucles for son útiles para repetir instrucciones que se van a producir un número determinado de veces. En este caso vamos a decirle que recorra toda la matriz y asigne un 1 a la posición que le digamos.

receptimetro(1,1) = 1

1 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

0 0 0 0 0 0 0 0 0 0

Para no hacerlo muy largo pensemos de forma más algebraica

a11 a12 a13

a21 a22 a23

a31 a32 a33

Cada elemento lo nombramos como aij

Como tenemos 10 filas necesitaremos un bucle con un contador para las filas. En cada fila hay 10 elementos, necesitaremos otro bucle que esté anidado en el primero para recorrer cada fila antes de pasar a la siguiente.

for i=1:10

for j=1:10

receptimetro(i,j)= 1

receptimetro = zeros(10); %Fijaos que como no quiero ir acumulando los unos en cada bucle, una vez terminadas las instrucciones le tengo que pedir que me vuelva a generar la matriz de ceros

end

end

Rayos y retruécanos Radiactivoman! En un plín Matlá ha hecho todas las matrices… pero ¿cómo trabajo con ellas? Eso es otro tema pero lo suyo será coger y meter todo el tochaco de instrucciones dentro del for, entre receptimetro(i,j)= 1 y receptimetro = zeros(10);

En cambio pensando en la práctica de Pilar y Ana la idea cambia un poco. Es cierto que Jesús ha dicho que hay que mapear una región de frecuencias, pero esa región no la podemos simplicar diciendo que es una matriz simple, en realidad es una matriz de pequeños vectores de dos elementos.

Aquí veo una matriz!

¿Pero qué dices alma de cántaro? Po si señoritas, yo ahí veo una matriz compuesta por elementos que en realidad son vectores. Recordad que en los script de prácticas definimos la frecuencia en x y en y, un par de frecuencias. Por supuesto que esto lo podemos trabajar como una matriz, pero en este caso nos hace falta que cada elemento de la matriz sean dos números diferentes. En C++ esto es muy fácil y cómodo de hacer, Matlá también lo sabe hacer pero de forma un poco más incómoda.

Jamemateeeeen! Ya veo que en cada elemento me interesan dos valores!

[1 1] [1 2] [1 3] …

[2 1] [2 2] [2 3] …

[3 1] [3 2] [3 3] …

Si alguien tiene curiosidad se hace con la instrucción struct (estructura). En otros lenguajes de programación cuando creamos una variable le debemos decir qué tipo de datos llevará, no es lo mismo escribir un natural, un entero, un decimal, un carácter, etc por cuestiones de memoria, desbordamientos, etc. Cuando le indicamos el tipo le podemos decir que la variable a es un vector de elementos de otro tipo concreto, pex: a es un vector de enteros y su longitud son dos elementos, y ahora puedo crear otra variable mediante la instrucción estructura y decirle que la estructura b es una matriz compuesta por variable a.

Que nadie se asuste a ver si le va a pasar como a Toni Genil en la isla… con dos bucles lo solucionamos! Lo que queremos son parejas de números y no vamos a recorrer ninguna matriz, nos imaginamos la matriz.

for i=min:max

for j = min:max

fx = i;

fy = j;

%Cálculos pertinentes

end

end

NOTA: en especial para Sarika y Paula, va por ustedes!

De la forma en la que hemos puesto el for, i tomará los siguientes valores: min, min+1, min+2

En vuestra práctica debéis trabajar con contrastes en valor decimal. Tenéis dos posibilidades:

  • Crear un vector con los contrastes

contrastes = 0:0.1:0.6

contrastes =

0 0.1000 0.2000 0.3000 0.4000 0.5000 0.6000

e ir diciéndole cógeme el elemento 1 del vector, después el 2…

    • Modificar el for para que el contador tome valores decimales. Se escribe igual que el vector contrastes:

for i=0.0:0.1:0.6

Ambas formas son iguales y a la vez diferentes. En la primera la variable i es un contador que nos va a servir para referirnos a los valores almacenados en un vector, de la segunda forma i es directamente el valor que queremos utilizar.

PD: quién lo lea que comente!!! 😉


Algunos consejos sobre programación para las prácticas

General maig 5th, 2011

Hola amiguit@s! Hoy estoy más despejadillo del resfriado y me han entrado ganas de escribir un poco. Voy a explicaros un pelín de Matlab a ver si hay algo que os es útil para las prácticas, especialmente para las de Psicofísica.

Matlab no es ni más ni menos que una calculadora, una calculadora cara y muy potente. Nos permite realizar una serie de trucos para hacer cálculos que o son tediosos o son repetitivos.

>> 1 + 2

ans =

3

También podemos crear variables, que es donde podemos almacenar resultados de nuestros cálculos

>> a = cos(pi)

a =

-1

Fijémonos en una cosa, mi variable se llama a, y le he dicho que me guarde el resultado de la operación coseno de π. Si os fijáis Matlab entiende que cos significa coseno y pi significa π. Por lo tanto existen una serie de palabras que Matlab tiene reservadas para nombrar funciones y constantes suyas que no podemos debemos utilizar para nombras nuestras variables (otros lenguaje de programación no permiten usar sus palabras reservadas.

Script

Un script es un archivo de texto con extensión .m, en el almacenamos una serie de instrucciones de Matlab. Copiando y pegando (o pulsando f9) las ejecutamos. Es la forma en que guardamos nuestro trabajo con Matlab y posteriormente lo podemos volver a ejecutar.

Como ejemplo supongamos que Matlab no sabe multiplicar. Una multiplicación es una suma repetida. Podríamos escribir la suma a mano (2 + 2 + 2), abreviar un poco usando variables ( b = 2345324623546234; b + b + b) o incluso guardarlo en un script. Pero, ¿y si queremos una solución más general que le de igual que queramos multiplicar por 2 o por tropocientosmil? Usaremos un bucle for.

Un bucle es una porción de código que se repite mientras que se cumpla una serie de condiciones. En el for la condición es que el valor de la variable contador (i normalmente) sea un valor natural que se encuentre entre el valor mínimo y el valor máximo. Esta variable nos va a almacenar cuantas veces se ha ejecutado el bucle, por defecto en cada iteración se incrementa su valor en una unidad.

Su sintaxis es:

for contador = inicio:fin;

instrucciones

end

En nuestro ejemplo el bucle será:

b = 0; % Aquí almacenaremos el valor del producto, debemos darle un valor inicial

for i = 1:fin

b = b + a;

end

Así con este script simplemente cambiando los valores de ai podemos calcular multiplicaciones. Si queremos refinarlo para no tener que editar cada vez el script podemos usar la función input. Esta función al ejecutarse presenta un texto en la línea de comandos de Matlab y guarda las pulsaciones de teclado que hagamos hasta pulsar intro.

var = input (‘Escribe un número ‘)

En nuestro ejemplo será:

a = input(‘Número a multiplicar: ‘);

fin = input(‘¿Por qué número lo multiplicas?: ‘);

b = 0;

for i = 1:fin

b = b + a;

end

display(‘El resultado de la multiplicación es ‘),display(b)

Genial, ahora nuestro script nos sirve para calcular productos de números naturales y encima está automatizado, al pulsar la tecla f9 nos preguntará los números a multiplicar y después nos dirá el resultado de la operación.

Aún lo podemos mejorar más porque, ¿y si en vez de abrir el script seleccionar y ejecutar el código buscamos una forma de ejecutarlo como una instrucción de Matlab? Quiero decir, ¿cómo convierto el script en una función?

Aquí conviene hacer una pequeña explicación sobre un pequeño matiz que Matlab no tiene en cuenta, la diferencia entre acción y función. Una función es como una función matemática, es decir, le das unos valores y te devuelve otros. En cambio una acción no devuelve ningún resultado. En nuestro ejemplo la diferencia sería: acción nos calcula la multiplicación, función nos calcular la multiplicación y además guarda el resultado para que podamos trabajar con el. También es útil si por ejemplo vuestro script tiene muchas líneas y lo queréis ejecutar muchas veces, se podría meter todo en un bucle for pero es más visible y elegante meter en un bucle una llamada a una función.

En Matlab es sencillo convertir un script en una acción, en la primera línea del script debe aparecer:

function nombre_de_la_acción

Y para una función:

function resultado = nombre_de_la_función (parámetro de entrada 1, parámetro de entrada 2, …)

Aquí resultado es la variable que devuelve y parámetro de entrada son los valores que se le deben pasar a la función

Entonces con todo esto nuestro ejemplo quedaría:

function res = suma_repetida

a = input(‘Número a multiplicar: ‘);

fin = input(‘¿Por qué número lo multiplicas?: ‘);

b = 0;

for i = 1:fin

b = b + a;

end

res = b;

display(‘El resultado de la multiplicación es ‘),display(b)

Ahora sólo queda guardar la función en una carpeta que esté en el “path”, de esta forma al decirle a Matlab:

y = suma_repetida

Buscará entre todos los archivos .m que tiene en su “path” y lo ejecutará.

Conclusión: después de todo el tocho desorganizado resumo un poco los puntos aprovechables.

    • Hemos aprendido cómo escribir y para qué sirve un bucle for
    • Hemos aprendido a usar las funciones input y display que son útiles para automatizar nuestros scripts y darle un toque más “pofesional”
    • Hemos aprendido a convertir el script en una función/acción

Bonus: Otras instrucciones muy interesantes.

while

Es otra forma de hacer un bucle, su sintaxis es

while expresión

instrucciones

end

Donde expresión tiene un resultado booleano (o se cumple o no) por ejemplo a ~= 6 (a no es 6). La diferencia entre while y for es que for realiza un número de iteraciones determinado y while no. Cuando no sabemos las veces que se va a repetir el bucle nos interesa utilizar while.

Por ejemplo, imaginemos que tenemos una serie de medidas en un vector muy largo y nos interesa detectar un valor mínimo, por ejemplo 2. Nuestra expresión podría ser i > 2. Veamos el código:

r = round(10.*rand(1,20)); %rand generará un vector fila de longitud 20 de números entre 0 y 1, los multiplicamos todos por 10

a = 200 %como queremos un valor mayor a 2 si lo inicializamos a 0 no se cumplirá la condición para que se ejecute while

i = 1;%Para Matlab el primer elemento de un vector ocupa la posición uno, en otros lenguajes el primer elemento ocupa la posición cero

while a > 2

a = r(1,i); %Dentro del bucle debe modificarse el valor de la condición o si no no terminará nunca!

i = i + 1; %Avanzamos una posición en el vector

end

display(i-1) % Que nos muestre la posición del primer valor que no cumple la condición, le restamos uno porque en el momento que deja de cumplirse la condición ya se le ha sumado uno a i

Aunque no parezca muy útil nos salva en los casos en los que no se puede aplicar fácilmente un bucle for.

if

Esta expresión si que mola porque es super útil. Veamos la sintaxis:

if expresión

instrucciones

end

Si se cumple la expresión se ejecutan las instrucciones, si no continua la ejecución desde el end.

Si lo aplicamos al ejemplo anterior, supongamos que queremos quitar el vector los valores menores que 2

for i = 1:length(r)

if r(1,i) >2

s (1,i) = r(1,i);

end

i = i+1;

end

Si lo ejecutamos después del código del while veremos como el vector s es más corto que el vector r ya que hemos quitado los valores que no nos interesaban.