miércoles, 27 de diciembre de 2006

Los insondables misterios de la informática

Bien háganse una idea...

Tengo un conjunto de datos, del que cada ciclo extraigo uno. Ese dato se almacena en un vector, bajo la condición de que la distancia con el valor anterior almacenado entre dentro de un umbral predeterminado. Si se sale del rango, asigno a ese ciclo el dato del ciclo anterior. Es un filtrado simple para evitar espúreos y es aceptable en el entorno de datos que estoy manejando. La idea es que el valor del vector representa un cierto estado, y solo permito cambios de estado de +- el umbral. En código de Matlab:

grupoDCT2(i) = datoSeleccionado;
if abs(grupoDCT2(i) - grupoDCT2(i-1)) > umbral
grupoDCT2(i) = grupoDCT2(i-1);
end


Ejecutando el programa donde va eso, me encuentro que en ciertos conjuntos de datos, el comportamiento es malo. Viendo los vectores resultantes, llego a la conclusión de que el problema está en el filtro, ya que dadas ciertas condiciones iniciales extremas, puede fastidiarlo todo.

Así que se me ocurre hacer una pequeña modificación en el programa, de manera que me queden dos vectores, uno filtrado y otro sin filtrar, para así poder comparar el efecto del filtro.

grupoDCT2(i) = datoSeleccionado;
if abs(grupoDCT2(i) - grupoDCT2Filtro(i-1)) > umbral
grupoDCT2Filtro(i) = grupoDCT2Filtro(i-1);
else
grupoDCT2Filtro(i) = grupoDCT2(i);
end


O sea, comparo el valor seleccionado en este ciclo, almacenado en grupoDCT2(i), con el valor anterior del vector filtrado. Al final debería tener dos vectores, teniendo en grupoDCT2Filtro el mismo vector que antes de las modificaciones. En principio yo diría que está bien, ¿no?

Pues va a ser que no...

El vector filtrado resultante era completamente distinto al calculado con la versión anterior del programa.

Tocaba revisar...

Y revisar...

Y revisar...

Después de darle ochocientas mil vueltas, he encontrado la solución:


grupoDCT2(i) = datoSeleccionado;
grupoDCT2Filtro(i) = datoSeleccionado;
if abs(grupoDCT2Filtro(i) - grupoDCT2Filtro(i-1)) > umbral
grupoDCT2Filtro(i) = grupoDCT2Filtro(i-1);
end


O sea, en vez de usar en la comparacion grupoDCT2(i) uso grupoDCT2Filtro(i), al que le he asignado el mismo valor que a grupoDCT2(i).

Y así funciona...

Estoy convencido de que hay alguna soberana chorrada que se me escapa, pero no he sido capaz de encontrarla...

En fin... Ya suelo decir que la informática es cualquier cosa menos una ciencia exacta...


2 comentarios:

ramonono | Maeghith dijo...

A mi siempre me han dicho que en estos casos se impone una traza sobre papel para entender que está pasando (de cabeza no, que se pasan cosas por alto, y es lo que se intenta evitar).

Aunque personalmente prefiero montones de echos (print/messagebox/whatever) en medio del programa para verificar el valor de las variables durante la ejecución del programa (trabajo mucho con scripts, y eso me apaña más que un debugger en el 90% de los casos), en lugar de trazas manuales. Además en bucles es divertidisimo XD.

PD: no he tocado nunca matlab, y no se si los arrays empiezan en -1 o en 0 (o si los puedes hacer empezar por lo que tu quieras), pero me mosquea el acceso a "grupoDCT2(-1)" que haría la primera iteración en la condición del filtro (también puede ser que lo hayas prefiltrado antes, pero como no lo has puesto, no lo veo).

PPD: replace("espúreo","espurio");

Wendigo dijo...

El problema de las trazas (que yo tb suelo usar a menudo) para mirar los valores esta en la cantidad de datos que tienes que manejar... El tamañano de grupoDCT2 varia entre los 600 y los 1200 elementos... Si el problema surje en los primeros ciclos, ni tan mal... Pero como empiece a partir de los 300 o 400 ciclos...

En Matlab los vectores empiezan en 1... Efectivamente, no se daría el caso de un indice -1 puesto que, por la manera en que se elige el datoSeleccionado, el filtro solo se ejecuta a partir de cierto numero de iteraciones (tipicamente 3)... De todas formas, el Matlab es muy quisquilloso, y si hubiese un indice 0 o -1 daria un error de ejecucion...

No pongo el resto del codigo pq son 350 lineas de puro dolor, que no se las daria a revisar ni a mi peor enemigo... A veces me cuesta entenderlas a mi, que las he escrito y se que es lo que se supone que estan haciendo, y eso que tengo comentarios en practicamente todas y cada una de las lineas... Cuando tienes que programar sin un objetivo concreto, añadiendo y quitando codigo para probar cosas es dificil hacer una planificacion y tener un codigo claro y ordenado... :3