jueves, 26 de diciembre de 2019

Sobre mi vida reciente II

Este ha sido un buen año para mi, es justo decirlo. En la segunda mitad de 2018 pasé unos meses bastante duros, honestamente no tenía muchas expectativas en enero. Pero en algún momento de febrero simplemente comencé a unir los puntos. Regresar a Mérida fue una sorpresa. Conocí a mucha gente increíble que ahora han hecho aún más grande mi grupo de "super science friends". Entré al fin a un posgrado (uno que años atrás, en una plática con un estudiante del CIC-IPN, me había parecido un reto muy alto). Tenía mucho que no sentía el haber aprendido más de lo que esperaba en un sólo año y que al fin, después de tanto funciono, bien otra vez.

Encontré un buen argumento más para escribir bitácoras públicas en un lugar inesperado, un librazo sobre inteligencia artificial que me recomendó uno de mis profesores: What to Think About Machines That Think. Pero necesito terminar de reconstruir el contexto antes de llegar a él. En Sobre mi vida reciente I me había quedado en mi sombría segunda mitad de 2018. Recibí 2019 en Zacatepec y regresé a Yucatán la primera semana de enero porque me habían aceptado para el SPI del CIMAT Unidad Mérida. Entre finales de febrero y la primera mitad de Marzo pasé mi última recaída psicológica y desde entonces me sentido como nunca. En mayo si no ml recuerdo me avisaron que había sido aceptado a la maestría en la UNAM (PCIC). Me ha gustado bastante hasta ahora. La carga de trabajo no es excesiva en volumen pero exige mucho tiempo de investigación, desarollo y depuración en el que caso de las tareas prácticas. En septiembre escribí lo siguiente en un estado:

"xkcd tenía una gráfica de conocimiento vs seguridad de saber. Había un pico cerca del origen y luego un valle muy grande, para después volver a subir alto después de mucho. He de estar en el valle porque a pesar de que cada semana aprendo a hacer cosas que se me hacían muy avanzadas para mí en la mitad licenciatura, sigo viendo lejos una capacidad real para resolver problemas de frontera. Porque es como caminar hacía el horizonte; avanzas solo para darte cuenta de que hay más y más camino para recorrer. En el caso de las ciencias naturales esto sería emocionante (¡tanto por descubrir y tan poco tiempo!), pero en las ciencias aplicadas me parece atemorizante (tanto por resolver, tantas herramientas por entender, y tan poco tiempo)."

Me siento más satisfecho con mi despeño desde entonces, pero no puedo evitar sentir ganas de evitar el estancamiento académico (en una sana medida, quiero pensar). La materia que más disfrute fue inteligencia artificial. Los dos profesores que la impartieron son excelentes. Uno de ellos fue el que nos dio una montaña de excelentes recomendaciones de libros de divulgación sobre distintos temas (incluyendo el que comentaba más atrás). La mejor razón que encontrado para escribir con más frecuencia aparece en un ensayo de Cesar Hidalgo: "No creo que las máquinas puedan pensar, pero tampoco creo que las personas puedan". En su opinión, la capacidad de pensar no es algo que este confinado en un solo individuo u objeto. Si una persona hubiera pasado años desde su nacimiento aislada en una cámara de supresión de estímulos, aislada del universo entero, no tendría nada en que pensar. La capacidad de pensar es una propiedad distribuida. Requerimos de la interacción con el mundo, de conversaciones, del conocimiento de la vida e ideas de otras personas para poder pensar. Creo que si más personas regresaran a escribir en bitácoras publicas (cada una con al menos un circulo de lectores significativo), aumentaría la capacidad de pensamiento y empatía en una escala social. No hace falta que se discutan temas profundos. Cada detalle de lo cotidiano es un bloque de construcción necesario. Espero regresar más a menudo al anecdotario y encontrar nuevos bloggers este 2020.

martes, 17 de diciembre de 2019

2006

Back then.
Si me dieran la oportunidad de regresar a 2006 pero sin saber lo que se ahora (en todos los aspectos), no lo aceptaría. El futuro (presente) sería diferente pero no necesariamente mejor ni habría disfrutado del tiempo mejor (dónde aplicaba). Este es mi argumento. Imaginen que se les da la tarea de organizar una biblioteca completa que tiene inicialmente todos los libros en desorden. Supongan que esto les toma dos años enteros. Al final, deciden crear un catálogo en donde aparece la posición correcta de cada libro en los estantes. Si enviaran ese catálogo a su yo de dos años del pasado justo antes de empezar, les tomaría quizá solo un mes ordenar todos los libros en vez de dos años. ¿Ven la idea? La información cuesta esfuerzo (sino de ustedes, de alguien más). Si amaneciéramos mañana en 2006 por una fallo en la matrix (como en la imágen que circula), estamos condenados a repetirlo todo (repetir en categorías, sería distinto por las pequeñas diferencias acumuladas [efecto mariposa] ). Suena un poco desalentador pero creo hay algo muy bueno en todo esto. Si no supimos aprovechar los buenos tiempos o no hicimos las cosas que nos hubieran hecho más felices, entonces no podemos culparnos porque la experiencia no puede crearse de la nada. Si tuvieron antes o tienen ahora las guías correctas, siéntense afortunados porque no existen los oráculos en la vida real.

nota: pueden encontrar aquí la versión formal de esta idea.

viernes, 6 de diciembre de 2019

Juego del gato (tic-tac-toe) vía algoritmo minimax.

Me dejaron el ejercicio de hacer un juego de gato y escogí el camino de la inteligencia artificial de la vieja escuela. Pensé que era algo trivial pero si me costó varios días. Planeo hacer en vacaciones un video sobre el algoritmo minimax en mi canal porque los que hay tienen códigos que ahora me parecen innecesariamente complejos. La verdad es que, aunque mis amigos creen que lo digo sólo por modestia, soy muy pendejo para entender las cosas a la primera y más aún si no me explican paso a paso. Ya que vi claro todo el proceso recursivo me acordé del final de la película War Games. Les debo el video pero por ahora pueden consultar mi reporte aquí. La implementación que hice hace uso de la siguiente clase para instanciar los estados posibles del juego:

Contiene un método que verifica si el tablero ya esta lleno y otro que verifica si es el turno del jugador X. El pseudocódigo es el siguiente:
[click para agrandar]


La función evaluación() retorna +10 si 'X' gana la partida, -10 si 'O' gana y 0 si hay empate o si aún no hay ganador en ese estado. El código completo en Python lo pueden encontrar aquí. Este programa sólo tiene el fin de ayudar a entender el algoritmo minimax. No es una implementación eficiente ya que resuelve el problema por fuerza bruta repitiendo incluso el paso por varios estados ya visitados. Pueden mejorarlo añadiendo estrategias como poda alfa-beta o memorizando estados ya visitados. 

jueves, 10 de octubre de 2019

Escrito sobre la salud mental: mi experiencia

Me parece que estamos entrando poco a poco a una buena época para la salud mental. Aún hay mucho por hacer, pero creo que para al menos mi generación, el estigma de la terapia psicológica está desapareciendo. Creo también que se está gestando una cultura de empatía, más allá del optimismo vacío tradicional. No soy un especialista pero tengo mucho que aportar con mi experiencia. Me incomoda ponerme al titulo pretencioso como "sobreviviente del desorden de ansiedad". Solo haré énfasis en que si pude salir de ese hoyo infernal y que si sé lo que se siente desear la muerte para apagar el miedo insoportable. Dicho eso también me he puesto en una posición de mucha responsabilidad. Confieso en que suelo sentirme mal  por llevar en mi saber lo necesario para cambiar la vida de tantas personas que están sufriendo pero no saber ni tener el poder para comunicarlo instantáneamente. Entiendo que es una responsabilidad distribuida porque la atención profesional es estrictamente necesaria. Pero el acompañamiento en el proceso para facilitarle las cosas a las personas es igual de necesario. Creo decir que tengo claro el método también puede dar las personas la expectativa de que daré un discurso de hombre sabio, que tendré la frase matadora que acabará de un golpe con el sufrimiento pero, por supuesto, las cosas no así. Y eso de hecho es parte central de lo que he aprendido. Esto me ha tomado varios años. Lo menciono no porque crea que este proceso debe ser necesariamente largo sino porque fui dando tumbos por la vida a prueba y error, pero juntando poco a poco los insights que terminé uniendo al final. Si pudiera enviarle una carta al pasado me habría ahorrado muchas cosas, ciertamente.

Les cuento uno. Era otoño del 2014, estaba esperado el camión una tarde en una esquina cerca del universidad en Puebla. Tenía un paraguas en medio de una llovía muy densa. No había una sola persona más en la calle. No iba ningún lugar en especial, solo trataba de despejar mi mente. Acaba de terminar una relación con una chica que había querido mucho. Me sentía terrible (esto fue dos años antes de que desorden de ansiedad me reventara en la cara). Pero de repente tuve una epifanía. Sentí de pronto que todo tenía sentido: mi dolor, la causa, el escenario. De repente me vi a mi mismo como el personaje de mi propia historia. No sentí felicidad pero era una sensación que podría llamar disfrutable. Sentía que aunque no era feliz en el sentido tradicional, mi queja no era la ausencia de contenido en mi vida. Lo que me parece interesante es que no sentí que fuera un cambio de "percepción" o una subjetiva manera diferente de tomar las cosas. Sentí como si acabara de descubrir una verdad metafísica de la realidad, algo fuera de mi de lo que había estado ciego [sidenote: quizá desde aquí me empezó a gustar el realismo literario].

Esta fue una de las muchas lecciones aisladas que años más tarde me ayudarían a sanar. 2016 fue el año en que me quebré. Cuento un poco en esta entrada. Si los que me leen saben el proceso entonces no aportaría demasiado en los detalles: insomnio, ataques de pánico y náuseas, etc. Dónde si lo haré es en las premisas más efectivas que encontré para salir del problema. Otra de ellas fue el entender que lo que llamamos sentirse bien es una habilidad, como saber bailar o dibujar bien. Esto no es nada evidente. Parecería que ser feliz es algo que simplemente ocurre sin mayor esfuerzo para unos pocos afortunados. La realidad es que si se tuvo la mala suerte de haber desarrollado esa habilidad (no haber tenido el ambiente correcto, la familia y amigos correctos, tenido malas experiencias, etc) se debe pasar por un proceso de desaprendizaje-aprendizaje. Creo que el error más grande que cometen los que se atascan en la terapia es suponer (en el fondo y sin hacerlo consciente) que su terapeuta un día les dirá las palabras mágicas que necesitan. Eso jamás pasará. Si entiendes verdaderamente que salir de un desorden es como aprender un nuevo idioma, ya estas del otro lado. Tercera cosa, el progreso no es una linea recta. Las recaídas son lo más normal del mundo. Vas bien. Esto me lleva a uno de los insights que más impacto tuvo en mi. Es una combinación de las tres últimas ideas más una observación extra. Durante una recaída intensa pero breve lo descubrí. Sentía de nuevo un malestar terrible, casi inmanejable por ratos. Lo mantuve a raya teniendo claro que no era nada anormal ni un retroceso y recordando que el sufrimiento es parte del contenido de mi historia personal. Pero lo que terminó destruyendo ese sentimiento de perdición fue una idea muy simple. Me dije una mañana al despertar a modo de broma. ¿Podría hoy sentirme sólo un poco menos miserable que ayer? Me di cuenta sin querer que si era posible. Sólo un poco menos que ayer, soportando el malestar sólo un poco más que ayer. Eso si era un objetivo alcanzable, nada de mierda de optimismo irracional. No diré el tiempo que tomó para no sesgar a nadie (cada quien es diferente), pero de poco en poco, así ha pasado ya mucho tiempo desde lo que fue mi última recaída y heme aquí intentando ser un profeta. No se si yo mismo hubiera seguido esta receta en mi época más oscura. Quizá sólo pude entenderlo después de todo lo que he vivido. Hay cosas que son incomunicables. Dicen los koanes del budismo que no se le puede enseñar a nadie el camino a la iluminación. Es un camino que las personas deben encontrar por su cuenta. Pero si con esto lo señalo aunque sea un poco, me doy por satisfecho.  

martes, 24 de septiembre de 2019

Luces atmosféricas

Se nombra atmosferic ghost light a un conjunto de fenómenos luminosos (la mayoría aún no explicados) que se reportan en muchas partes del mundo. Son tan relativamente comunes y la evidencia fotográfica y relatos anecdóticos son tan similares que tengo la sospecha de que se trata de procesos geofísicos que valen la pena investigar. En el caso de México, he escuchado en varios pueblos de Morelos, Guerrero y Puebla historias sobre "brujas", fantasmas de fusilados de la revolución y, por supuesto, ovnis que se aparecen volando en las cumbres de los cerros o en las entradas de las cuevas. Por un lado, mi hipótesis del origen natural de estas luces es algo que no les gusta oir a los aficionados a los ovnis o lo paranormal, y por el otro, es una propuesta de investigación que sería difícil de tomar en serio en la academia. Así que cazar estos objetos sería una aventura científica personal si lo llegara a llevar a cabo. Existen algunos vídeos en Youtube que me parecen reales, aunque me dan gracia algunos de sus títulos:
Algo muy recurrente es las historias de estos avistamientos, especialmente en los comentarios de personas que los han visto de cerca, es un ruido similar al de la estática en el radio y un olor a "estéreo quemado" [ozono]. Estas son dos características de fenómenos eléctricos de alto voltaje. Podrían tratarse de alguna forma de rayo esférico aunque no he escuchado ningún reporte durante la lluvia. Incluso en algún foro de buscadores de tesoros leí una historia de quemaduras internas [aunque la palabras que en realidad usaron fueron "hechizo de bruja"], lo que me haría sospechar de ondas estacionarias de microondas, que en principio serían requeridas para confinar un plasma esférico. Comparen el vídeo anterior con este otro:
El cerro de la Silla es mucho más alto, pero la posición relativa de las luces es similar. Si lo comparan ahora con este video de un rayo globular, comenzaran a notar también que aquí hay un patrón. La geografía de los 3 videos es muy similar. Otro lugar famoso muy similar es el Punto Marconi o "Cerro del Ovni" en Atlixco, Puebla donde también se reportan luces en las cumbres de los cerros de la zona. Probar mi hipótesis de los rayos globulares no sería sencillo. Estos fenómenos están muy ampliamente diseminados y no ocurren con tanta frecuencia. Sería muy útil tener un mapa con las etiquetas geográficas de todos los lugares en México dónde se reportan este tipo de fenómenos. Luego compararlos con los mapas de suelos y encontrar alguna correlación con las características físicas del terreno (si es zona sísmica o la abundancia de ciertos minerales en el suelo). Teniendo ese mapa, el siguiente paso sería construir una estación de instrumentación electrónica autónoma. Podría ser un módulo de bajo costo con cámara, estación meteorológica básica, con una Raspberry Pi alimentada por un banco de baterías recargadas con celdas solares y un enlace de comunicación LoRa. Con más presupuesto, un espectroscopio para tener más información sobre el proceso que genera la luz.

Si tienen curiosidad, aquí hay otras luces atmosféricas reportadas en otras partes del mundo:

domingo, 22 de septiembre de 2019

Registro de imágenes con SIFT en OpenCV

Se le llama registro al proceso de trasformación entre varios conjuntos de datos que permiten "encajar" o superponer patrones similares. Quizá el proceso más conocido sea la creación automática de fotos panorámicas a partir de varias fotos independientes. En esta entrada haremos un ejemplo más sencillo. Observen estas dos fotografías de un mismo objeto (uno de mis libros favoritos) tomadas en ángulos diferentes:
Lo que haremos sera colocar la imagen de la izquierda con la misma orientación y escala que la imagen de la derecha. Tomaremos de referencia las características comunes entre ambas imágenes (el libro principalmente). ¿Cómo encontramos estos puntos? En 2004 David Lowe publicó un algoritmo llamado SIFT (Scale-Invariant Feature Transform)  que permite encontrar puntos clave invariantes a las rotaciones y, en buena medida, a los cambios de iluminación. Los puntos clave con mejor correspondencia entre ambas imágenes se ven así:
Este algoritmo está patentado y no aparece en la instalación estándar de OpenCV. Deben seguir las instrucciones que puse en mi entrada anterior para poderlo utilizar. El código que escribí es una modificación para SIFT del código que pueden encontrar acá. Lo he reducido y comentado para mejor claridad:
La imagen final registrada es esta:

sábado, 21 de septiembre de 2019

Instalar OpenCV-Python con SIFT y SURF habilitados

Quiero ahorrarles algunas horas y frustración con esto. Estas notas están hechas para Linux (uso Debian) pero posiblemente funcione también en Windows (no lo garantizo). Voy asumir que ya tienen instalado Anaconda... Primero tienen que crear un nuevo entorno virtual (esto es por seguridad y no dañar su entorno principal de Python por si algo malo ocurre). Para crear un nuevo entorno:

$ conda create --name mi_entorno_OpenCV -y

Pueden nombrar su entrono como quieran pero es buena idea ponerle un nombre que haga referencia a su modulo. Si trabajan con IA seguramente necesitarán un nuevo para Tensorflow. Ahora, si es la primera vez que crean un entorno virtual tendrán que configurar su terminal para permitir que conda administre los entornos virtuales:

$ conda init bash

Si no usan bash debe poner la shell que utilicen. Bien, una vez que hayan hecho esto pueden activar su entorno con:

$ conda activate mi_entorno_OpenCV

Notarán que habra cambiado la etiqueta antes del promp y deberá aparecer el nombre de su entorno. Deberán instalar ahora matplotlib (su nuevo entorno solo tendrá numpy y scipy [si no, deberán instalarlos también]):

$ conda install -c conda-forge matplotlib

Spyder tampoco estará instalado en su nuevo entorno así que deberan instalarlo también:

$ conda install -c anaconda spyder

Recomiendo leer Managing enviroments de la documentación de conda. Ahora si, para instalar una versión de OpenCV que permita utilizar los algoritmos SIFT y SURF deberán instalar específicamente esta:

$ pip install opencv-contrib-python==3.4.2.16 

Listo. Terminada la instalación pueden hacer una prueba con los códigos de ejemplo de la documentación de OpenCV. Recuerden que deben mandar a llamar a Spyder desde la terminal con el entorno virtual que crearon para OpenCV. para salir del entorno utilicen:

$ conda deactivate

 En la próxima entrada pondré un ejemplo utilizando el algoritmo SIFT.

sábado, 14 de septiembre de 2019

Messidor

Si me preguntan a mí, The Durutti Column inventaron el Post-Rock en 1981 con la canción Messidor. Aparece en su segundo álbum: LC. Esta canción se adelanta casi 20 años a su época e incorpora mucha de la estructura y el estilo en las guitarras que le podemos escuchar a The Explosions in The Sky.


sábado, 31 de agosto de 2019

Sobre mi vida reciente I

Esta misma semana pero del año pasado tuve un cambió total de mi estado de ánimo de una manera que no hubiera previsto. Antes de llegar a ella necesitamos ir a diciembre de 2017...

Me había titulado de la BUAP en septiembre y para ese entonces estaba acabando de vender o regalar la mayoría de mis cosas. Me despedía de mi último hogar en Puebla. Mas que nostalgia me paso por la mente un arrepentimiento. Tenía una amiga que había sido vecina de pensión por algunos años. Nos habíamos confesado que nos gustabamos en 2015. Yo acaba de tener una ruptura de la tardé en recuperarme y ella tenía novio en ese entonces. Nunca pudo haber nada entre nosotros, una porque se fue hacer su tesis a un centro de investigación en Atlixco y dos, porque yo tuve mi colapso psicológico [desorden de ansiedad generalizada] a principios de 2016. Para julio de 2017 mi psicóloga me dijo que el tratamiento había terminado. Me sentía bien para entonces, con algunas recaídas menores, pero lo suficientemente renacido para seguir con mi vida. Ya había trazado mi plan. Aplicaría a la maestría en Sistemas Embebidos de la Universidad de Southamton en Reino Unido. Para finales de noviembre ya había asistido a las sesiones informativas de becas de posgrado al extranjero de una organización que no quiero ni mencionar. Sentía que tenía el destino a mi favor. Regresando a diciembre, solo en mi pequeño cuarto de Tres Cruces, me arrepentía por nunca haber intentado nada con C. Se me ocurrió salir con ella para despedirme, contarle mis planes y mi arrepentimiento. Cuando la vi, unos pocos días después, me dijo que estaba en Puebla porque había ido a las sesiones informativas de las becas de posgrado en el extranjero. '¿A dónde piensas ir?', le pregunté. "A Groningen, Holanda", me dijo para mi sorpresa. Eso cambió por completo mi speach para ese día y cambió un poco el curso de mi historia.

Valdría la pena contar todo lo que ocurrió después de esa tarde pero brincaré hasta julio de 2018. Precisamente, entre el 11 y el 24 de julio, cuando se vinieron abajo todos mis planes. C consiguió la beca estatal (de un estado vecino), le avisaron antes de la fecha oficial. Yo estaba esperando a revivir los mios de Puebla. Cuando la fui a ver, el 11, lo recuerdo, me dijo que había cambiado de opinión, que las cosas no iban funcionar estado en lugares diferentes estudiando un posgrado. Quizá tenía razón, pero no debió llenarme el oído de tantas cosas los meses anteriores. Sentí de repente que yo no era una persona por la que valiera la pena intentar algo. Partí al día siguiente, molesto, a Jojutla, Mor. Alejado del resto del mundo en la casa de mis abuelos era el mejor lugar para pensar las cosas con calma. El 20 llegó el seguido golpe: me negaron la beca. Ese día me sentía confundido si saber exactamente que pensar o sentir. Uno dos días después me cayó la realidad y empecé a retorcerme en llanto en una cama. Hice varías llamadas a mis amigos más cercanos. El hecho de ser muy abierto emocionalmente es una válvula de escape muy útil. Dos o tres días después me sentía bien de nuevo... hasta que casi de la nada tuve la peor recaída de ansiedad de mi vida. Ciertamente los sucesos de los días anteriores la habían detonado, pero no sentía que la alimentaran. Esto debe de las cosas más difíciles de explicar para los que hemos pasado por un desorden de ansiedad. La gente creía que estaba así por la beca pero en realidad lo que más preocupaba en ese entonces era mantenerme cuerdo. Empecé a tener episodios de hipocondría muy intensa por dolor de garganta que no se me quitaba. Mi miedo era tan grande que pensé en quitarme la vida (así los absurdos del desorden de ansiedad). Para principios de agosto comencé a retomar el control y las cosas comenzaron a mejorar mucho. Creí que había escrito una entrada sobre las primeras semanas de agosto. Pasaron cosas muy interesantes que definieron todo lo bueno que estoy haciendo ahora, pero me saldría del hilo principal de esta entrada. Cuando creí que ya estaba todo bien cambié una por otra. Para cuando comenzaba a desaparecer la ansiedad comenzó a crecer una depresión en mi. Para la segunda mitad de agosto había pasado del miedo a la indiferencia por la vida.

El 23 de agosto ocurrió entonces lo que me hizo ver mi vida de otra manera. Esa mañana, mi abuelo resbaló (o perdió el equilibrio, nunca lo supimos) y se fracturó la cadera. Ese fue el inicio de unos de los episodios más difíciles para mi familia. Mi abuelo ya sufría de demencia senil y el estar forzado a estar en una cama lo volvió muy violento y difícil de controlar. Mi mamá llegó desde Mérida pocos días después. Las noches era largas. Teníamos que turnaros para cuidarlo y detenerlo cuando intentaba pararse de la cama. Siempre nos insultaba y a veces nos golpeaba. Mi mamá y mi abuela lloraban de la desesperación. Pero en medio de ese caos, de repente me sentí como nunca antes. Sentía que mi vida tenía sentido. Si bien tuvimos el apoyo de la familia y amigos, no era posible que estuvieran las 24 horas con nosotros. Eramos sólo nosotros tres quienes tenían que lidiar con la tarea día y noche. Nunca sentí enojo por mi las cosas que hacía o decía mi abuelo. Sabía que la persona que habíamos conocido ya se había ido hace unos años por el progreso de la enfermedad. Mi mamá y mi abuela no parecían entenderlo y les afectaba mucho. Tuve varias pequeñas recaídas pero manejables y me levantaba en pocos días. No tenía opción realmente, tenía que estar bien para poder ayudar. Mi abuelo falleció en noviembre. Le lloré mucho en su momento, pero en el fondo sentíamos que tenía finalmente el descanso que merecía por una larga vida tan activa, novelesca y un final tormentoso. No sabré nunca que sería de mi vida sin todos estos giros. Mi última recaída fue en marzo y me he sentido muy bien y resiliente todos estos meses. Quisiera poder compartir el "método" que he seguido pero ni yo lo tengo claro. Estas cortas memorias son lo mejor que puedo hacer.

lunes, 15 de julio de 2019

Gráficas de Maplotlib en Tkinter

He estado aprendiendo usar el módulo TKinter para hacer interfaces gráficas en Python y me está encantando. A pesar de no tener un asistente gráfico como pyQT, se me ha hecho bastante fácil de usar. Para incrustar gráficos de Matplotlib en un GUI de Tkinter pongo el siguiente ejemplo en donde cada botón manda a graficar una función diferente:

  

martes, 9 de julio de 2019

martes, 2 de julio de 2019

Áreas, perímetros y centroides de imágenes binarias con scikit-image

Utilizando las funciones label() y regionprops() del submódulo measure de scikit-image podemos obtener varios parámetros muy útiles de regiones binarias contiguas (blobs binarios). En este ejemplo construiremos una imagen binaria con dos círculos de diferente tamaño de los cuales obtendremos sus propiedades.

Las salidas del programa son:

Región 1:
Area (pixeles): 15361
Perimetro (pixeles): 458.2741699796952
Centroide: (80.0, 100.0)


Región 2:
Area (pixeles): 7825
Perimetro (pixeles): 326.3919189857866
Centroide: (220.0, 220.0)

Es posible  construir un dataframe de pandas a partir del diccionario de propiedades generado con la función regionprops_table(). Si están comenzando con scikit-image pueden revisar mis notas de mi curso introductorio aquí.

viernes, 7 de junio de 2019

Generar imagenes PNG de ecuaciones en LaTeX

El archivo que pueden usar como plantilla es el siguiente:

Para poder generar el PNG deben colocar --shell-escape como opciones para el compilador. En Texmaker/TeXstudio pueden hacerlo yendo a Opciones->Configurar Texmaker/TeXstudio:
Yo utilicé esta función para hacer en Gimp stickers matemáticos impresos en papel couché adhesivo:

Nota: Si usas Windows es un poco más complicado: LaTeX to PNG on Windows.

martes, 7 de mayo de 2019

Mecanografía y terminal

El primer paso que debe darse para el dominio natural de la terminal de Linux es tener la habilidad de escribir rápido en el teclado sin mirarlo. Creo que el no ser capaz de hacerlo es el impedimento más grande para enamorase de la terminal y de los editores de texto de consola como Vim o EMACS. La imagen que he puesto en esta entrada es una modificación que hice en GIMP de la asignación de teclas para cada dedo en un teclado latinoamericano. La posición de las manos debe ser la siguiente:
Tomar cursos de mecanografía es recomendable, pero es posible aprender por cuenta propia únicamente practicando con las imágenes anteriores. Pueden intentar con este ejercicio en un bloc de notas o editor de texto sencillo como calentamiento:

mop map mop map mop map
mop map mop map mop map
mop map mop map mop map
 ...
dec sec dec sec dec sec dec 
dec sec dec sec dec sec dec
dec sec dec sec dec sec dec 

 Deben mantener la vista fija en la pantalla sin voltear hacia los dedos y respetando la asignación de teclas de cada dedo. Si nunca lo han hecho antes será bastante difícil. Notarán que una de las cosas más difíciles es retomar la misma posición después de borrar o después de cada nueva linea (enter). Lo importante es tener mucha paciencia hacerlo muy muy lento al principio. Los resultados los verán poco a poco y les aseguro que valdrán la pena, en especial si siempre han querido escribir como hackers en frente de una terminal.

Una buena herramienta de práctica la pueden encontrar en esta página:


Insisto, no se fijen en los errores ni en las palabras por minuto de sus primeras prácticas. Comiencen lento. Tal vez pasen días antes de sentirse fluidos. La cosas en nunca dejar de practicar. 

viernes, 19 de abril de 2019

Fenestra Coeli Apertae

Johann Jakob Scheuchzer. Fenestra Coeli Apertae (The Windows of Heaven were Opened), Physica Sacra. 1731.

jueves, 28 de marzo de 2019

De regreso en la divulgación

La semana pasada y antepasada, di unas charlas sobre comunicaciones por radio en una primaria al sur en Mérida. Use mi dongle de SDR FunCube. Noté que a los niños les llamó bastante la atención el "arcoíris de radio" (como les digo para hacer referencia al espectrograma) y la demodulación del FM qué hago con SDR# en tiempo. No pude controlar a los de 4to mucho tiempo (son los de esta foto) pero los de 6to estuvieron muy tranquilos y entendieron perfectamente bien cómo funciona la modulación digital FSK y ASK. En todos los años que llevo haciendo divulgación científica he visto una y otra vez la capacidad de los niños de entender conceptos complejos si se encuentra la manera adecuada de presentarlos. Me molesta bastante que se les trate como tontos. Afortunadamente me invitaron a un nuevo grupo de difusión científica llena de excelentes personas: Asociación Juvenil de Ciencia Yucatán. He estado en varios grupos de divulgación pero este verdaderamente tiene miembros con un equilibrio perfecto entre entusiasmo y talento. Esto es algo que no digo todos los días (i. e. soy muy mamón a la hora de evaluar proyectos y personas) y aún más curioso considerando sus edades, la mayoría estudiantes de segundo semestre. Llevo poco tiempo conviviendo con los miembros y en sus eventos ya he hecho nuevos amigos muy interesantes. El tipo de amigos que me hubiera gustado tener en mis primer año en Puebla.

martes, 26 de marzo de 2019

Sobre el por qué documentarlo todo

Como a muchos, si no es el caso de la mayoría, odiaba documentar mis proyectos en la universidad hasta que entendí su utilidad. Los problemas, sin importar su tipo, están muy a menudo relacionados unos con otros. Cada problema que resuelves puede significar tiempo ahorrado en un problema futuro. Entre más problemas hayas resuelto, mejores son tus probabilidades de resolver tus siguientes problemas en menor tiempo. Pero esta experiencia no se organiza de forma automática en tu mente (bueno fuera que si). Para aplicar el principio que comento es necesario llevar un registro detallado de tus soluciones. Esta es mi regla: "documenta como si tú yo del futuro fuera a olvidarlo todo". Es decir, no puedes confiar en que el futuro seguirás teniendo en la memoria todos los pequeños detalles que le dieron contexto a tus soluciones. En otras palabras, "date a ti mismo la solución que te hubiera gustado que te cayera del cielo en ese momento". No es necesario ser muy formales en la redacción si es una documentación personal. Tengo varias libretas de "Príncipe Mestizo" llenas de taches y correcciones con lo que funcionó y no funcionó, y este mismo blog es también la versión on-line de mis apuntes. Tan pronto vean los resultados de esto amarán registrarlo todo. Siempre y cuando lo hagan de una manera fácil de consultar cuando sea requerido, les garantizo placeres profesionales. 

lunes, 25 de marzo de 2019

Gráfica de lecturas de un DHT11 en Python

Esta nota corta será para no olvidar como hacer una gráfica en Python de un conjunto de mediciones de temperatura a lo largo del tiempo. El sensor utilizado en un DHT11 (que muy tardé me di cuenta que tenía muy baja resolución y que es mejor el DHT22). Generé un archivo de texto a partir de comunicación serial entre un PIC y una Raspberry Pi dónde cada linea tiene la siguiente estructura:

2019-03-22 23:11:33,22,46
fecha, temperatura, humedad relativa 

Algo muy útilil que aprendí a hacer es trasferir archivos entre un host local y la Raspberry a través de la red con un solo comando de consola. El comando es scp y su sintaxis es la siguiente para copiar del host local a la Raspberry :

$ scp /un/dir/local/archivo usuario@ipremota:/un/dir/remoto/archivo

Y de la Raspberri al host local:

$ scp usuario@ipremota:/un/dir/remoto/archivo /un/dir/local/archivo

Ya con el archivo en mi computadora, utilicé el módulo Pandas para leer el archivo .txt dónde registre cerca de dos dias y medio de datos de temperatura y humedad relativa. Aplique un filtro de mediana con el modulo scipy.signal para quitar los picos abruptos en los datos. Finalmente realice los ajustes necesarios para mostrar únicamente la hora en el eje x. El programa completo es el siguiente:

Gráfica:

martes, 19 de marzo de 2019

CIAA

Hace unos días en un grupo de Facebook me ayudaron con una duda que me tenía intranquilo y no puedo expresar lo agradecido que estoy. Me especialicé en sistemas digitales y comunicaciones y no sé nada de manejo robusto de transientes e interfaces en entorno industrial. Resulta que los benditos argentinos tienen un proyecto de hardware y software abierto de sistemas de cómputo para entornos industriales llamado CIAA (Computadora Industrial Abierta Argentina). Tienen absolutamente todo lo que requería, diagramas de la circuitería de protección, documentación, tesis, pruebas ¡Todo! Esto me ahorra meses enteros de trabajo. Tenía muchas dudas sobre el como implementar circuitos de protección robustos para tarjetas de aplicación de microcontroladores (PIC, AVR, STM32, etc.) aptas para soportar las condiciones de un entrono industrial. Este es el el espíritu del hardware y software abiertos que tanto defiendo: llegar más lejos echándonos la mano entre todos.

lunes, 18 de marzo de 2019

LCD en MPLAB X / XC8

Había comentado en una entrada pasada que las nuevas versiones de XC8 dejaron de usar Peripheral Library y en esa misma entrada explico el truco que pueden hacer para utilizarla. Sin embargo, los usuarios de PIC's modernos deben saber lo cómodo que es usar ahora MCC. Pero también habrán notado que no hay un generador de código para el manejo de LCD's.  Así que he hecho un fork en GitHub de una librería hecha por Manolis Agkopian a la que hecho una mínima modificación para poder usarla en el PIC18F45K50. Pueden acceder a los códigos aquí. Esta librería me parece genial porque te permite usar el puerto que quieras, a diferencia de la mayoría que he visto que te limitan a un puerto fijo (que debes modificar si quieres usar otro). Lo único que deben hacer es agregar los archivos lcd.h y lcd.c a los headers de su proyecto. Como aún hay muchos usuarios del PIC18F4550 voy a poner aquí un ejemplo con él.  Usaré una tarjeta Miuva a 48 MHz: 

martes, 12 de marzo de 2019

Máquina de Estados Finitos en C [PIC18F45K50]

Para esta implementación en software de una máquina de estados finitos (FSM: Finite State Machine) haremos uso de punteros a funciones [click en el enlace para ver un video-tutorial]. Usaremos también  el compilador XC8 en MPLAB X y un PIC18F45K50 con las mismas configuraciones que en la entrada anterior.

En una gran cantidad de problemas a resolver mediante un sistema embebido es necesario llevar a cabo un proceso estrictamente secuencial. En estos casos es muy útil y elegante estructurar nuestros programas como una máquina de estados. Quizá muchos de ustedes estén tentados a usar una estructura case para elegir un segmento de código cuando se cumple una condición. Si el numero de estados es pequeño, quizá se una opción fácil. Desafortunadamente el uso de case's es muy ineficiente cuando la máquina de estados y su tabla de transiciones es muy compleja. La implementación que se mostrará en esta entrada parecerá un tanto rebuscada pero tiene la ventaja de tener buen despeño a la hora de escalarla a numero grande de estados.

El diagrama de estados de la FSM de este ejemplo es el siguiente:
Diagrama hecho en LaTeX con TIKz
Las entradas 0/1 representan los estados de un switch conectado a RB0. Los estados se harán visibles enviando el numero correspondiente al Puerto D [esta acción será definida en la función asociada a cada estado]. Obsérvese que está máquina describe a un contador ascendente o descendente según la entrada. Se agregará un retardo de un segundo para poder visualizar las transiciones.

Movámonos al programa. Primero, debemos definir un tipo enumerado para codificar nuestro conjunto de estados:

//-- Definición de tipo de estados
typedef enum {
    Estado_0,      // Estado inicial
    Estado_1,
    Estado_2,
    Estado_3,
    Estado_4,      
    No_de_Edos
} ESTADOS;

Creamos con esto una variable enumerada global que usaremos para almacenar el estado actual de la máquina:

//-- Variable global de estado
ESTADOS Estado_Actual = Estado_0;

El siguiente paso es definir una estructura que nos permitirá construir un objeto para nuestra FSM:

//-- Estructura de Maquina de Estados (FSM))
typedef struct {
    ESTADOS Estado; // Estado miembro del conjunto enumerado ESTADOS
    void (*func)(int); // Acciones asociadas al estado         
} FSM;

Con lo anterior podemos ahora crear una instancia que sera nuestra FSM:

//-- Prototipos de funciones de estado
void Codigo_EDO_0(int);
void Codigo_EDO_1(int);
void Codigo_EDO_2(int);
void Codigo_EDO_3(int);
void Codigo_EDO_4(int);

//-- Creación de la estructura global de la FSM
FSM Maquina_de_Estados[] = {
    {Estado_0,Codigo_EDO_0},
    {Estado_1,Codigo_EDO_1},
    {Estado_2,Codigo_EDO_2},
    {Estado_3,Codigo_EDO_3},
    {Estado_4,Codigo_EDO_4},
};

Es importante que los prototipos de las funciones asociadas a cada estado aparezcan antes de la creación de la estructura (estas funciones serán definidas más adelante en el código). El segmento de código principal queda reducido elegantemente de la siguiente manera:

void main(void) {
    int sw = 0;
    setup();
   
    //-- FSM ---
    while(1){
        sw = PORTBbits.RB0;
        (*Maquina_de_Estados[Estado_Actual].func)(sw);
    }
    return;
}

Código completo:
Circuito utilizado:

viernes, 22 de febrero de 2019

Iniciando con el PIC18F45K50 / 25K50 en XC8

El PIC18F4550 es uno de los microcontroladores más populares entre estudiantes y hobbistas. Sin embargo ya es algo viejo (no tiene soporte para MCC , los K50 si). Poco a poco, se está migrando a su sustituto más nuevo: el PIC18F45K50. En México, fecha de 2019, aún no es muy fácil de conseguir en tiendas pero puede comprarse con envío gratis en Newark Mexico. Si nunca han usado MPLAB con XC8 aquí hay un tutorial bastante bueno (con PIC16, pero estén pendientes a mi canal porque subiré un curso para los K50). Vamos a realizar una práctica sencilla para comenzar a familiarizarnos con este MCU: Prender y apagar un led conectado a RB0 mediante un switch conectado a RD0 con un reloj a 48 MHz. Tengan a la mano la datasheet y vayamos por partes:

1. Configuración del reloj

El esquema de reloj es distinto al de su antecesor [pag. 29]. Usando un cristal de 16 MHz, este es el camino que debe estar habitado para conseguir los 48 MHz:
Click para agrandar
Los configuraciones necesarios son las siguientes:

#pragma config PLLSEL = PLL3X
#pragma config CFGPLLEN = OFF // ver Tabla 3-3 
#pragma config CPUDIV = NOCLKDIV
#pragma config FOSC = HSM     

#pragma config PCLKEN = ON  

 2. Configuración de puertos

Los pines RB0 y RD0 son usados por el módulo ADC por lo que deben desactivarse para ellos. En el caso del puerto B, esto puede hacerse al generar la cabecera de fuses con la linea:

#pragma config PBADEN = OFF

Para el caso de RDO deberá hacerse en el código principal escribiendo en el registro ANSELD [la tabla con todos los registros de función especial está en la página 84 de la datasheet] :
 3 Código completo en C

Como regla general siempre se debe leer en puerto y escribir  en latch:

lunes, 4 de febrero de 2019

Toolbox de Control para Python

Para aquellos que busquen un sustituto de código abierto para Matlab hay una buena noticia: Existe el módulo Python Control Systems Library. Acabo de probarlo y me parece mucho mejor que otras alternativas como los toolbox de control para Scilab y Octave. Si usan Anaconda, pueden instalarlo desde la terminal usando conda:

$ conda install -c conda-forge control

Quiero mostrarles algunos ejemplos simples utilizando el modelo de un motor NXT de Lego que describo en una entrada anterior. El modelo es el siguiente:
Creamos el objeto del modelo de la siguiente forma:

#Modelo como función de transferencia
num = [193.3]
den = [1.0, 18.735, 0.0]
sys = ctrl.tf(num,den) #Lazo abierto
print(sys)


El print nos mostrara la función de transferencia como una fracción en texto (al igual que en Matlab). Vamos a graficar ahora la respuesta al escalón de la planta en lazo cerrado:

#Modelo en lazo cerrado
sys_cl = ctrl.feedback(sys,1)

#Respuesta al escalón
t,y = ctrl.step_response(sys_cl)


#Graficas
plt.plot(t,y)
plt.grid(True)
plt.title(u"Respuesta al escalón")
plt.xlabel("segundos")


Lo que nos dará el siguiente resultado:
Para obtener el diagrama de bode:

plt.figure(2)
ctrl.bode_plot(sys)


Para visualizar el diagrama de polos y zeros:

from control.pzmap import pzmap 

plt.figure(3)
polos,zeros = pzmap(sys_cl), plt.grid(True)
print(polos[0])
print(polos[1])


¡Trataré de crear notebook's con más ejemplos y subirlos en mi GitHub!

viernes, 1 de febrero de 2019

This Must Be The Place

Hoy descubrí una canción que no conocía de The Talking Heads que ahora quisiera escuchar por el resto de mi vida. Se me ha quedado muy grabado en la mente uno de los comentarios del video. Just buried a dear friend after his long battle with a cruel disease. Instead of a moment of silence, he requested this song be played. Momentos después, un tanto por accidente, me puse a escarbar en la antigua blogosfera. Suelo añorar la época en la que gente escribía con frecuencia sobre sus vidas e ideas. Entre blog y blog empecé a notar que la mayoría parecieron detenerse entre 2009 y 2011, habiendo algunos que aguantaron hasta 2013. De todos hubo uno que atrapó mi atención. El (no tan) maravilloso mundo del Jedi... Suelo saltarme las primeras entradas para tratar de recuperar la secuencia temporal. De haber leído la última entrada hubiera adelantado lo que averigüé después. El autor me cayó bien, de esas personas que hubiera disfrutado leer en 2008. Una costumbre de ex-blogger es mudarse a Twitter así que se me ocurrió buscarlo ahí. Su último tweet, fechado el 10 de agosto de 2013, era una corta despedida. Por un enlace a su Facebook publicado desde su Twitter me di cuenta, por los comentarios de sus amigos y familia, que había fallecido por leucemia en septiembre de 2013. Había visto perfiles de dueños ausentes antes, pero nunca uno tan lleno de escritos abundantes de buenos detalles. El tipo de cosas que muchos quisiéramos que nos escribieran al dejar el mundo. Sin haberlo conocido puedo decir que fue una persona que verdaderamente supo dejar huella en la gente. Incluso en un extraño como yo. This Must Be The Place me suena en la mente como el final de una pelicula.

miércoles, 23 de enero de 2019

Tres libros que verdaremante pueden cambiarte la vida

Al menos lo han sido para mí y considero buena idea hacer algunos comentarios. No me considero muy bueno haciendo reseñas pero creo que si puedo puntualizar por qué me hicieron cambiar mi modo de ver la vida.

The Practicing Mind (Ejercita Tu Mente en la edición en español), Thomas Sterner. Es un libro corto que te da una idea simple pero poderosa. Es una observación aparentemente obvia pero yo no vi hasta muchos años adelante en mi vida: Cada minuto de práctica/estudio cuenta y los minutos se acumulan con el tiempo. Ninguna habilidad se crea de la nada (ni se nace con ella), sino que debe crearse paso a paso a través de la práctica. El libro explica a detalle la profundidad que se oculta en esta idea y los consejos para llevarla a la práctica. Sin duda un libro que hubiera cambiado enormemente mi vida si lo hubiera leído a los 15 o 12.

Learned Optimism (Aprenda Optimismo), Martin Seligman. De acuerdo a las investigaciones del Prof. Seligman los consejos de este libro me habrían evitado muy probablemente el desorden de ansiedad generalizada contra el que luché por casi dos años. Y así lo creo. No se dejen engañar por el título que suena a superación personal barata. Lo digo teniendo una mente científica que no se traga cualquier cosa. En la definición del autor, optimismo es el entendimiento de que nuestras acciones cuentan y que, en la mayoría de las veces, tenemos mucho más control del que creemos, todo esto sin caer en una fastidiosa "actitud positiva" ciega.

Attached (Maneras de Amar), Amir Levine. No creo que en pocas lineas pueda hacer justicia a la manera en que este libro me abrió los ojos a todos los errores que había cometido en mi vida amorosa. Pueden quizá omitir mis anteriores recomendaciones, pero no esta. Este libro debería ser lectura obligatoria en la secundaria o preparatoria. El libro aborda el tema de de los modelos de apego en las relaciones humanas y de como aplicarlos para elegir a una pareja que se adecue a nuestro modo de apego y hasta incluso rescatar una relación. Les puedo asegurar que cuando lo lean lamentarán no haberlo hecho antes.

lunes, 21 de enero de 2019

Leer imagenes .BIL del INEGI con Python

Los archivos de Banda Intercalada por Linea (BIL) es un formato de archivo binario en el que las distintas bandas de una imagen se concatenan formando una única matriz de datos. Los disponibles en la página del INEGI suelen tener una sola banda por lo que su extracción resulta aún más sencilla.

Para este ejemplo vamos utilizar fotografías aéreas. Vamos a ir a la pestaña de Datos, luego Mapas y finalmente a Topografía que nos mostrará este mapa. Seleccionamos la escala de 1:20,000 y nos aparecerán cuadriculas sobre el territorio y seleccionamos la que sea de nuestro interés. Al momento en que escribo esta entrada la página tiene un bug y muestra el mensaje de "No existen mapas relacionados con esta carta" cuando se da clic en cualquier zona y se podría pensar que no hay datos disponibles para ella, pero los datos aparecerán más abajo. Voy a utilizar una fotografía que cubre parte del municipio de Jojutla de Juarez, Morelos [archivo E14A69e]. Los archivos vienen en una carpeta comprimida ZIP. La información requerida para extraer los datos (dimensiones y formato) viene en un archivo .txt. En este caso el archivo es e14a69e.txt:

El programa de lectura y visualización es el siguiente:

La visualización de la imagen resultante es esta:

miércoles, 9 de enero de 2019

Cómo usar un MOSFET de potencia como interruptor

Primero, lo que debemos entender es que a diferencia de los transistores BJT, los transistores FET son conmutados por voltaje y no por corriente. Específicamente, los FET son controlados por la diferencia de potencial que existe entre la compuerta (G) y la fuente (S). Para los MOSFET, la corriente de drenaje (I_D) es proporcional al voltaje Vgs siempre y cuando este voltaje supere un valor de umbral como se muestra en la siguiente figura [Principios de Electrónica, Bates-Malvino]:
Podemos ahora poner en práctica esta consideración y simular un circuito de conmutación de una carga usando un IRF150. Este MOSFET puede aguantar un voltaje Vds de hasta 100V y una corriente Id de hasta 38A, pero usaremos una fuente de 30V solo como ejemplo. Elegiremos un voltaje Vgs de 15V para garantizar la corriente de saturación:
Vemos que este circuito funciona correctamente. Este modo se conoce como Low-Side. ¿Pero que ocurrirá si requerimos que la carga a conmutar deba estar por debajo del MOSFET [High-Side]? Si hacemos la simulación de este nuevo caso notaremos un problema:
Lo que se observa en este caso es que el voltaje entre las terminales G y D supera el voltaje de umbral pero no es lo suficientemente grande para garantizar la corriente de saturación. Esto es un problema muy común a la hora de construir inversores para convertir CD en CA. Este problema se resuelve utilizado un driver de boostrap como pueden ser el IR2001 o el IR2010. La siguiente simulación ejemplifica la manera correcta de conmutar un MOSFET con la carga por debajo:
Es importante señalar que este modo de conmutación no funciona de manera indefinida debido a la descarga del capacitor. Pero en aplicaciones de PWM funciona perfectamente siempre y cuando se elija un valor de capacitancia que mantenga encendido al MOSFET durante todo el ciclo de trabajo. En la práctica la conmutación de potencia suele realizarse desde un microcontrolador, así que recomiendo checar los modelos de drivers de conmutación que maneja Microchip tanto para Low-Side como High-Side y utilizar opto-acopladores ya que el voltaje de encendido supera los 10V en la mayoría de los MOSFET's de potencia.