Diego García Díaz
GIS & Remote Sensing. Python & Statistics. Surf & MTB :)
Primera pregunta:
¿Que productos mantener en Nor?
Se han buscado imágenes Landsat 8 y 9 posteriores a la fecha de la primeras imágenes de Landsat 9 (2021-10-31) que estuvieran completamente libres de nubes.
Una vez seleccionadas las escenas se procedió a ver el histograma de las bandas 1 y 2 (Coastal blue y blue).
Las siguientes escenas cumplían los requisitos:
LC08_L2SP_202034_20220802_20220806_02_T1
LC08_L2SP_202034_20220818_20220824_02_T1
LC08_L2SP_202034_20230805_20230812_02_T1
LC09_L2SP_202034_20230712_20230714_02_T1
LC09_L2SP_202034_20230728_20230802_02_T1
Finalmente la decisión ha sido la escena Landsat 8 del 2 de agosto de 2022.
Se ha preferido una Landsat 8 porque parecen radiométricamente más coherentes que Landsat 9 y porque están disponibles desde 2013, habiendo por tanto muchas más escenas en ese periodo.
20220802l8oli_202_34
Imagen de referencia:
Nomenclatura:
Formato:
El código está hecho y funcionando, a falta de normalizar las escenas para probarlo con las imágenes normalizadas
El mayor esfuerzo de tiempo se ha empleado en la mejora de la máscara de máxima inundación. Se trata de un enfoque dinámico basado tanto en donde puede haber agua como en donde no puede haber agua:
P10 >= 0.4
Mean >= 0.4
(rs < 0.13 & Fmask >= 5 | dtm <= 5) | (rs < 0.13 & (ndvip10 < 0.4 & slope < 10 & cobveg < 90)
Nomenclatura: 20200920l8oli202_34_grn2_swir1_b5*.tif
Valores y formato: Reflectividades 0-1 (float32. GeoTiff)
Escena de referencia Landsat 8 para todo la versión 2
Carpetas: ori, geo, rad**, nor, pro, hyd, data
Productos: NDVI, Flood, Depth***, Turbidity, LST, Hillshade
* ¿Cambiar wavelength por banda?
**¿Borrar geo y rad (momento)?
***Añadir método DTM
Valores Flood: 0 (Seco), 1 (inundado), 2 (NoData)
Estructura y uso del Protocolo
Máscara de agua. Comparativa breve de algunas escenas
Tareas a seguir para concluir esta v2
Próximos pasos en la automatización
Productos, MongoDB, Hidroperiodo
__init__.py
download.py
protocolov2.py
productos.py
hidroperiodo.py
utils.py
run_download.sh
run_hydroperiod.sh
protocolov2.py
Métodos
__init__(ruta_escena) get_hillshade() get_cloud_pn() remove_masks() projwin() coef_sr_st() normalize() nor1(banda, mascara, std=1) nor2l8(banda, slope, intercept)
run()
El proceso de normalización comienza pasando la ruta a la escena original de Landsat (Colection 2 Level 2).
El método run() se encarga de ejecutar todo el proceso. En primer lugar se realiza la descarga del quicklook de la escena y se añade la entrada a la base de datos (MongoDB).
A continuación se genera el Hillshade con los datos solares obtenidos del MTL, posteriormente se reclasifica y recorta Fmask con el shape del Parque Nacional. Pasamos a recortar la escena con el shape del WRS 202-34 y a aplicar los coeficientes para tener las reflectividades en 0-1.
Finalmente pasamos a la normalización, controlado el flujo por normalize, nor1 para obetner los parámetros y nor2 para aplicarlos y guardar las bandas normalizadas
productos.py
Métodos
__init__(ruta_nor) ndvi() ndwi() mndwi() flood() turbidity() depth() get_flood_surface()
run()
La obtención de productos comienza instanciando la clase pasando la ruta a la escena normalizada.
Los productos a fecha de hoy son NDVI, NDWI, MNDWI, Flood, Turbidity y Depth, otros*. Existe otro método get_flood_surface() que es el que obtiene la superficie inundada de los recintos principales de la marisma**.
El método run() va ejecutándolos todos y guardando la información en la base de datos
**¿Polígonos de censo aéreo?
*¿Otros productos?
***LST***
Base de datos (MongoDB)
hidroperiodo.py
funciones
get_escenas_values()
get_hydroperiod()
get_products()
Gini() & IRT()**
El hidroperiodo no es una clase sino un script con 3 funciones.
La primera get_escenas_values() se encarga de calcular los días "que vale" cada escena del ciclo hidrológico (1 de septiembre - 31 de agosto).
La segunda get_hydroperiod() calcula el número de días que un pixel ha estado inundado o seco o ha sido NoData.
La tercera get_products() genera los rasters con los hidroperiodos y el número de días válidos del ciclo para cada pixel.
Valid days
Hydroperiod
Base de datos (MongoDB)
utils.py
funciones
enviar_correo(destinatarios, asunto, cuerpo, archivo_adjunto) proceso_finalizado(info_escena, archivo_adjunto) prepare_hydroperiod(productos_dir, output_dir, ciclo_hidrologico, umbral_nubes)
En utils.py se engloban las dos funciones para mandar el correo con la información de la escena y una función para preparar los datos para ejecutar el hidroperiodo.
Los mails se mandan desde la cuenta de gmail del LAST lastebd.protocolo.vlab@gmail.com
al terminar de procesar una escena. Informa sobre la cobertura de nubes, la superficie inundada y adjunta el quicklook de la misma.
La función del hidroperiodo se encarga de copiar las máscaras de agua agrupadas por ciclo
download.py
funciones
download_landsat_scenes(username,
password,
latitude,
longitude,
days_back=15,
end_date=None,
process=True,
max_cloud_cover=100,
output_dir='path/to/save/rars')
Es donde sucede "la magia". Se trata del script que se encarga de buscar escenas nuevas para el rango de fechas seleccionado, cotejarlas con la base de datos y en caso de no estar, realizar la descarga y llamar a las clases Landsat() y Product() para procesar la escena. Si todo va bien, termina enviando un mail llamando a las funciones de utils.py
run_download.sh --> download_landsat_scenes()
run_hydroperiod.sh --> prepare_hydroperiod(), get_escenas_values(), get_hydroperiod() y get_products()
Son dos archivos bash que son los que se añaden al crontab para que se ejecuten una vez a la semana (run_download.sh) y una vez al año (run_hydroperiod, que se ejecutará cada 15 de octubre)
Archivos en /nor
Archivos en /pro
Archivos en /hyd
/hidroperiodoYYYY-YYYY/
La máscara basada en Fmask, aunque mejora bastante a la anterior, sigue sin ser perfecta.
Buscar una metodología que no depende de ningún tipo de máscara de zonas inundables, sino de definir en que zonas no podríamos detectar agua aunque la hubiera.
dtm
fmask_escena
hillshade_escena
ndvi_escena
ndwi_escena
mndwi_escena
cob_veg
ndvi_p10
ndvi_mean
fmask
mndwi
ndwi
swir1
Criterios:
Swir1 <= 0.12
slope > 8 (**embalses NDWI_scene & MNDWI_scene**)
hillshade < p30
ndvip10 > 0.3 & ndvimean > 0.5
cobveg > 75
ndvi_scene > 0.6 & dtm > 2.5
fmask_scene clouds & shadows
sum(reclass((fmask_scene, ndwi_scene, mndwi_scene)) >= 2
Conclusiones comparativa v1-v2
Issues Colection 2 Level 2
- Nuevos Productos
Finalización v2
- Procesado de toda la serie y dejar máquina virtual corriendo los sh con crontab
Nuevos satélites/sensores
*** Se normalizan las S2 con las PIAs***
***Se normaliza la imagen de referencia de S2 con la de Landsat***
***Read the Docs & video tutorial***
- Envio Geoserver
Los productos de inundación no son perfectos, especialmente en zonas de sombras que no quedan enmascaradas por las sombras en el Hillshade (ej. zonas urbanas) y en algunas zonas de invernaderos (sobre todo plásticos negros)
La idea es ir mejorando el producto, aún así, no funciona peor que el anterior y, a riesgo de ser crucificado, creo que tanto la inundación como el hidroperiodo han mejorado con respecto a la versión 1.
Se han normalizado más escenas que en la versión 1. Al ser la descarga automática, se procesan (y hasta normalizan!) escenas que de haberlas comprobado manualmente probablemente se hubieran descargado
¡Necesidad de validación (productos y normalización)!
¡Necesidad de nuevos datos de campo!
Se va a procesar nuevamente la colección 2 (~1 semana)
para incluirles Máscara de nubes alternativa a TM y ETM+ y relleno de gapfill a ETM+
- Se ha incluido el envío de mail en caso de que no se normalice la escena (añadiendo porcentaje de superficies por recintos)
- Se ha añadido el método apply_gapfill con GDAL
- Se ha añadido el procesado con la máscara de nubes alternativa a Fmask en las escenas TM y ETM+
- Pruebas (exitosas) con Geoserver (Ya se podrían mandar los rasters al terminar cada escena)
A decidir:
1) De verdad gapfill?
2) Estructura y nomenclatura en /pro
3) Umbral de nubes para el hidroperiodo (automático?)
4) Data type. Propuesta seguir en float y eliminar /ori (748 gb) y los rasters auxiliares (~250 gb) de hidroperiodo
5) COG!?
A realizar:
* Cruce con lagunas Carola y Censo aéreo
* Exportar a PostgreSQL
* Flood DTM
* Línea de costa
* Read the Docs
* Videotutorial
250 dias agua
110
110
110
220
By Diego García Díaz
GIS & Remote Sensing. Python & Statistics. Surf & MTB :)