5. Especificación avanzada

Introducción

La especificación avanzada es un nueva característica de las versiones 3.x del plugin. Este tipo de configuración tiene una lógica diferente a la forma habitual de especificar los parámetros, porque la estructura es distinta.

En esta parte del tutorial nos dedicaremos a estudiar las ventajas de usar la especificación avanzada en un script

¡Comencemos!

Estructura y lógica

Así como en la especificación normal las líneas de parámetros tenían una estructura, también la especificación avanzada tiene una estructura que debe mantenerse. La lógica es la siguiente:

1##QgsProcessingParameter<Tipo>|Nombre|Descripción|<Otros Argumentos separados pipe>

Comienza por dos signos de numeral (##), seguido del nombre de la clase del parámetro en la API de QGIS (QgsProcessingParameter*) y los argumentos de la clase separados por una barra vertical (|). Para entender esta estructura debemos conocer la API de QGIS, ya sea la versión de C o la de Python. Lo que debemos buscar son los detalles de las clases QgsProcessingParameter<tipo>: A continuación una tabla con las clases QGIS y el correspondiente parámetro de entrada de Processing R

Parámetro Tipo QGIS API
vector QgsProcessingParameterFeatureSource
raster QgsProcessingParameterRasterLayer
number QgsProcessingParameterNumber
string QgsProcessingParameterString
boolean QgsProcessingParameterBoolean
Field QgsProcessingParameterField
color QgsProcessingParameterColor
range QgsProcessingParameterRange
datetime QgsProcessingParameterDateTime
Band QgsProcessingParameterBand
extent QgsProcessingParameterExtent
crs QgsProcessingParameterCrs
enum QgsProcessingParameterEnum
enum literal No disponible 1
file QgsProcessingParameterFile
folder QgsProcessingParameterFile (behavior: 1)

Especificación avanzada para salidas

Al momento se soportan cuatro tipos de parámetros de salida para especificación avanzada:

Incluyendo en un script

A fin de entender como usar la especificación avanzada convertiremos el Script de ejemplo Min_Max que viene con el plugin QGIS Processing R en un script con especificación avanzada.

Las líneas que nos interesan cambiar son de la 3 y 4:

 1##Example scripts=group
 2##Min_Max=name
 3##Layer=vector
 4##Field=Field Layer
 5##Min=output number
 6##Max=output number
 7##Summary=output string
 8
 9Min <- min(Layer[[Field]])
10Max <- max(Layer[[Field]])
11Summary <- paste(Min, "to", Max, sep = " ")

Así es como se ve la herramienta actualmente. Las flechas indican las partes donde tendrán efecto nuestros cambios

Vista de la herramienta antes de la modificación

Empecemos cambiando entonces la línea ##Layer=vector por otra donde la variable se siga llamando "Layer", pero la descripción sea un texto más descriptivo, por ejemplo "Capa de entrada". Luego cambiaremos también la línea ##Field=Field Layer, donde especifiquemos que sea de tipo "Number" para no tener problemas con los campos de texto.

 1##Example scripts=group
 2##Min_Max=name
 3##QgsProcessingParameterFeatureSource|Layer|Capa de entrada
 4##QgsProcessingParameterField|Field|Variable|None|Layer|0|False|False
 5##Min=output number
 6##Max=output number
 7##Summary=output string
 8
 9Min <- min(Layer[[Field]])
10Max <- max(Layer[[Field]])
11Summary <- paste(Min, "to", Max, sep = " ")

El reemplazo de la línea tres es ##QgsProcessingParameterFeatureSource|Layer|Capa de entrada para la cual solo se ha definido el tipo de parámetro, el nombre de la variable y la descripción. Pero si te fijas en la API, esa clase tiene cinco argumentos, ¿Qué pasó con los demás?.

1QgsProcessingParameterFeatureSource(
2    name: str, 
3    description: str = ‘’, 
4    types: Iterable[int] = [], 
5    defaultValue: Any = None, 
6    optional: bool = False
7    ) 

Los parámetros no especificados tienen valores por defecto que se pueden prescindir en la especificación. Esto funciona porque la asignación de los valores es posicional. En el caso de la línea 4, sucede que el quinto y sexto argumento necesitan ser especificados, por lo tanto se debe escribir todos los demás valores (por lo menos) hasta que corresponda con la posición correcta para el valor que queremos cambiar. En este caso, la capa padre del campo y el tipo de campo.

 1QgsProcessingParameterField(
 2    name: str, 
 3    description: str = ‘’, 
 4    defaultValue: Any = None, 
 5    parentLayerParameterName: str = ‘’, 
 6    type: QgsProcessingParameterField.DataType = QgsProcessingParameterField.Any, 
 7    allowMultiple: bool = False, 
 8    optional: bool = False, 
 9    defaultToAllFields: bool = False
10    )

En la imagen a continuación se muestran los efectos en la herramienta. Nótese que las descripciones de los textos han cambiado y también se han reducido las opciones en la lista de campos posibles.

Vista de la herramienta después de la modificación

✨ ¿Qué pasó con el cuerpo del script?

El cuerpo del script no ha cambiado en nada, seguimos manteniendo los nombres de las variables usadas desde el principio. Por lo tanto este script sigue funcional.

Ejercicio

Ahora es tiempo de practicar. Tu tarea será cambiar una o varias líneas del script "Zonal mean from top N" disponible en los scripts del taller. Los datos del ejemplo están disponibles gracias a la amable contribución de Castillo, L. (2022)2.

👌 Tip!

Si has instalado correctamente el plugin Qgis Resources Sharing y el repositorio del taller, deberías tener los scripts visibles en la caja de herramientas de processing.

Puedes seguir los siguientes pasos:

  1. Clic derecho sobre el script "Zonal mean from top N" y clic en Edit script...
  2. En la ventana que se abre tienes todo el script, pero solo nos interesan las lineas de la 4 a la 8. Puedes decidir cual de ellas quieres intentar cambiar.
  3. Dependiendo la línea que hayas elegido puedes ir a la documentación de la API de QGIS y buscar los argumentos que correspondan para ese parámetro. Aquí tienes accesos directos como ayuda:
  4. Agrega una línea de documentación con la clave #' ALG_CREATOR:<Tu nombre>, para saber quien hizo la modificación
  5. Cuando hayas terminado de editar guarda los cambios y prueba tu herramienta.
🤞 Ayuda

El contenido a continuación ha sido ocultado intencionalmente. Despliégalo solo si sientes que no puedes realizar el ejercicio por tu cuenta.

Haz clic para mostrar el contenido de ayuda.

Si has instalado correctamente QGIS processing y tienes disponible el script mencionado, puedes abrir la edición del script y reemplazar todo el contenido con el siguiente:

 1##Taller UseR!2022=group
 2##zonalmeantopn=name
 3##Zonal mean from top N=display_name
 4#Raster=raster
 5##QgsProcessingParameterRasterLayer|Raster|Capa raster
 6##QgsProcessingParameterFeatureSource|Zonas|Capa vector de zonas|2|None|False
 7##QgsProcessingParameterField|Zonas_Ids|Campo de identificador único de zonas|None|Zonas|-1
 8##QgsProcessingParameterNumber|Top_N|Número máximo de valores más altos|0|100|False|1
 9##QgsProcessingParameterVectorDestination|Zonal|Capa de promedio por zona
10
11Zonas_rst <- raster::rasterize(Zonas, Raster, field = Zonas_Ids)
12mean_top_100 <- function(x, top = Top_N, na.rm = TRUE) {
13  if(na.rm) x <- na.omit(x)
14  if(length(x) < top) {
15    top <- length(x)
16    message("Zone has less than top n values defined. Calculating with availables")
17  }
18  mean(x[which(rank(-x) <= top)][seq_len(top)])
19}
20Stats <- raster::zonal(Raster, Zonas_rst, fun = mean_top_100)
21colnames(Stats) <- c(Zonas_Ids, paste0("mean_", Top_N))
22Zonal <- merge(Zonas, Stats, by = Zonas_Ids)
23
24#'Raster: Capa raster
25#'Zonas: Capa vector de polígonos que representan las zonas
26#'Zonas_Ids: Campo de la capa de <em>Zonas</em>
27#'Top_N: Valor numérico entero que define los n de valores más altos. 
28#'Zonal: Salida vectorial con el promedio de las <em>n</em> valores más altos
29#'ALG_CREATOR: @gavg712

  1. Este parámetro es por ahora un truco del plugin para obtener los textos a partir de un enum. Futuras versiones de QGIS vendrán un nuevo parámetro denominado QgsProcessingParameterEnumString, pero no ha sido implementado todavía en este plugin. ↩︎

  2. REFERENCIA: Castillo, Luis. (2022). Altura de los árboles. Post-procesamiento de datos de la primera cobertura LIDAR (año 2009), Cabeza de Fraile, Valencia. España (1a ed.) [Raster]. Centro de Nacional de Información Geográfica de España. ↩︎

Traducciones: