En los últimos días, como siempre en el día a día del desarrollo de software, viví un viaje lleno de altos y bajos mientras trabajaba en la optimización de la previsualización de imágenes satelitales en una aplicación Python+FastAPI en la que estoy trabajando.

La aplicación ya había logrado desarrollarse con éxito para dar soporte a las imágenes de Landsat 8 y 9. Sin embargo, el nuevo reto fue incluir a Sentinel-2. La previsualización de imágenes de Landsat era perfecta desde el principio, lo que me hizo pensar que la integración de Sentinel-2 sería igual de sencilla. Sin embargo, pronto descubrí que estaba equivocado. Las imágenes de Sentinel-2 no cargaban y generaban múltiples errores de configuración con las bandas y demás. Luego, cuando logré que se previsualizaran, estas aparecían casi completamente oscuras, un problema frustrante que parecía no tener solución inmediata.

Mis primeros intentos para solucionar el problema con Sentinel-2 fueron en vano. Ajusté parámetros de visualización, modifiqué configuraciones y revisé la documentación innumerables veces, pero las imágenes seguían viéndose oscuras. Cada ajuste que hacía para intentar arreglar Sentinel-2 parecía descomponer algo en Landsat, llevándome a un punto de desesperación. Era como una manta corta: al cubrir un lado, dejaba el otro descubierto.

La mayor parte de las funciones lógicas que atienden los requerimientos científicos específicos que requieren ser analizados, son desarrolladas por personas del equipo que lidero. Este equipo multidisciplinario de desarrolladores senior y junior junto a personal especializado en otras ramas orienta la conceptualización, diseña y desarrolla los algoritmos, y evalúa los resultados que producen los algoritmos de análisis en Google Colab, Jupyter Notebooks y/o Deepnote y cuando están listos, los integramos a la aplicación de producción. Este enfoque colaborativo es esencial para garantizar que las soluciones sean robustas, eficaces y precisas. A pesar de este esfuerzo colectivo, a veces es fácil descuidarse con la precisión que requiere tener la configuración de cada tipo de imagen.

Después de bastantes intentos intermitentes, finalmente encontré la raíz del problema. Descubrí que las imágenes de Sentinel-2 requerían una normalización diferente de los valores de reflectancia. Mientras que las imágenes de Landsat funcionaban bien con un rango de 0 a 30000, las de Sentinel-2 necesitaban valores entre 0 y 0.3. Este pequeño pero crucial ajuste cambió todo. Ahora podía ver las imágenes de Sentinel-2 con claridad y detalle, un gran alivio después de tanta frustración.

A pesar de este avance, me di cuenta de que estos cambios iniciales habían hecho que las imágenes de Landsat se vieran completamente blancas. Claramente, necesitaba una solución que pudiera ajustarse dinámicamente a las necesidades específicas de cada satélite. Implementé una lógica condicional muy simple para aplicar los parámetros de visualización correctos según el satélite seleccionado. Este ajuste básico no solo resolvió el problema de las imágenes oscuras de Sentinel-2, sino que también restauró la funcionalidad de Landsat.

Este proyecto ha sido una ruleta de aprendizajes. Desde el momento en que Jhonny López me compartió el requerimiento inicial en el que se debían determinar la arquitectura y tecnologías para obtener, recortar, clasificar, presentar los resultados y anticipar cada posible caso de uso inesperado para el futuro, hasta la satisfacción de encontrar una solución viable para cada situación que se va presentando en el día a día, cada paso me ha enseñado algo nuevo. A través de este proceso, redescubrí la importancia de la paciencia y la persistencia, así como el valor de las soluciones simples y elegantes.

Antes de adoptar FastAPI, esta aplicación estaba desarrollada con Flask. Decidí migrarla a FastAPI para poder ofrecer una API a desarrolladores externos que ya tienen una plataforma para descarbonización y que van a mostrar datos generados con el motor de nuestra aplicación. Esta migración fue otro desafío y seguramente tendrá suficiente tema para otra historia, pero permitió que la aplicación sea más robusta y escalable, facilitando la integración con otras plataformas y mejorando el rendimiento general.

Además de los desafíos técnicos, la arquitectura de esta aplicación también es un logro en sí misma. Está construida con Python y FastAPI, gestionada con Poetry para manejar las dependencias, la cual antes se manejaba con PIP pero que por sugerencia de un colega tuvimos que migrar, y el despliegue a través de contenedores Docker. Actualmente, la versión en desarrollo está desplegada en Azure, mientras que la versión en producción se encuentra en AWS. Las imágenes se almacenan en Google Cloud Storage y la aplicación se comunica con diversas APIs externas para completar su funcionalidad.

Cada obstáculo es una oportunidad para aprender y mejorar. Esta historia continuará…