Introducción al desarrollo con PyQGIS
Germán Carrillo
Introducción al desarrollo con PyQGIS
2020
Sobre mí...
MSc. en Geoinformática (Münster, Alemania)
Colaborador oficial de QGIS desde 2009!
Co-administrador de GeoTux
Coordinador general de QGIS Colombia (2018-2020)
¿Dónde me encuentras?
Curso de introducción a PyQGIS
Introducción
"Creemos que por lo menos algunos analistas realmente necesitarán aprender a programar.
Piensa en ello como aprendiendo a cocinar. Puedes preferir pasta fresca a macarrones gratinados en caja, pero si no quieres quedar atrapado comiendo la última, debes aprender a cocinar o pagar a alguien más para que lo haga por ti.
Aprender a programar es como aprender a cocinar de otra manera: puede ser un proceso muy gradual. Un día estás sentado comiendo tus macarrones gratinados y decides mejorarlos con un poco de Tabasco, mostaza o salsa inglesa. Bingo! Pronto estarás poniéndole además queso rallado. (Continúa...)
Curso de introducción a PyQGIS
Introducción
(...) Descubres que los ingredientes que compras para un plato pueden ser mezclados para hacer otro. Empiezas a quedarte un rato en el pasillo de las especias en el supermercado. La gente empieza a comprarte utensilios de cocina. Llegas al punto donde eres capaz de experimentar con recetas.
Aunque pocas personas se conviertan en chefs, muchos aprenden a cocinar suficientemente bien para satisfacer sus propias necesidades.
Si no programas, tu proceso de investigación siempre estará a merced de aquellos que lo hacen."
Traducido de http://sgillies.net
Curso de introducción a PyQGIS
Introducción
Así como en la cocina, en programación se cometen errores...
Curso de introducción a PyQGIS
Introducción
Así como en la cocina, en programación es normal olvidar ingredientes, y es normal recurrir a la documentación, o incluso al código de otros...
Curso de introducción a PyQGIS
Materiales del curso
Curso de introducción a PyQGIS
Python
Curso de introducción a PyQGIS
Introducción a Python
Guido van Rossum, principios de 90's
Inspirado en 'Monthy Python'
Lenguaje interpretado (semi)
Tipado dinámico y fuertemente tipado
Multiplataforma
Sintaxis sencilla que lo hace muy legible
Curso de introducción a PyQGIS
Bases de Python
¡Escribamos algo de Python!
Intérprete de Python
Tipos de datos
Condicionales y ciclos
Funciones
Curso de introducción a PyQGIS
PyQGIS
Curso de introducción a PyQGIS
Introducción
Curso de introducción a PyQGIS
Recursos y documentación
QGIS API (C++):
QGIS API (Python):
PyQGIS Cookbook:
https://docs.qgis.org/latest/en/docs/pyqgis_developer_cookbook/
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
1. Consola de Python y editor de scripts
Ctrl
+
Alt
+
P
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
2. Macros del proyecto
Proyecto --> Propiedades...
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
3. Acciones
Propiedades de la capa --> Acciones
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
4. Expresiones personalizadas en Python
Diálogo de expresiones --> Editor de Funciones
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
5. Algoritmos de Geoprocesamiento
Ventana de Procesamiento --> Scripts
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
6. Plugins
Curso de introducción a PyQGIS
¿Dónde usar Python en QGIS?
7. Scripts 'standalone' (sin la GUI de QGIS)
Curso de introducción a PyQGIS
¡¡¡Empecemos!!!
1. Consola de Python y editor de scripts
Curso de introducción a PyQGIS
Pero antes de empezar...
¡Necesitamos saber qué es una clase y qué es un objeto!
Curso de introducción a PyQGIS
Programas más comprensibles y más fáciles de mantener.
¡Se basa en Objetos!
Los objetos:
Programación Orientada a Objetos
Representan mejor la complejidad del mundo real.
Tienen estado y comportamiento.
Interactúan con otros objetos.
Curso de introducción a PyQGIS
Caso 1: Aplicaciones gráficas (Qt5).
Los objetos son: ventanas, botones, diálogos, etc.
Caso 2: Aplicación para SIG (QGIS).
Conclusión:
Y... ¿Qué son los objetos?
"Un objeto es la representación de un concepto
en el sistema."
Los objetos son: tablas, capas vectoriales, capas ráster, un mapa, la simbología de una capa, botón 'Acercar', etc.
Curso de introducción a PyQGIS
Un objeto es una representación. Es concreto y particular.
Ejemplo: Botón “Acercar mapa”, Botón "Panear".
Clases y objetos
Las clases se agrupan en librerías:
Ejemplo: Librería Controles gráficos de usuario (GUI).
Incluso se puede hablar de cosas más generales, esto es,
de clases más abstractas. Ejemplo: Clase Botón.
Para conceptos (generales) se habla de Clases.
Ejemplo: Clase Botón de navegación.
Curso de introducción a PyQGIS
Conceptos (abstractos) del sistema.
Pueden actuar como moldes o prototipos para crear objetos.
Tienen propiedades y métodos.
Clases
La clase Botón puede tener...
Propiedades como: Size, Text, Icon
Métodos como: run()
El objeto Botón "Acercar mapa" también tiene:
Size (32x32), Text (""), Icon (acercar.png), run() (acercar.py)
Los objetos de una clase, heredan sus propiedades y métodos.
Curso de introducción a PyQGIS
Concluyendo sobre clases y objetos
Clase (Concepto, plantilla, molde)
Objeto (Instancia de una clase)
Imágenes: https://www.iconfinder.com/icons/4835095/code_coding_page_programming_web_web_page_icon
https://www.iconfinder.com/icons/618630/bubble_dream_happy_idea_speech_talk_think_icon
Curso de introducción a PyQGIS
Comunicación con QGIS
Cuando abrimos QGIS, podemos acceder a sus objetos
QgisInterface
iface
Curso de introducción a PyQGIS
Escribiendo código en PyQGIS
Escribamos código Python para manipular información
geográfica...
Usando iface
Accediendo a capas y a sus propiedades
Creando campos
Análisis espacial (cruce de capas)
Modificando capas
Curso de introducción a PyQGIS
1. Consola de Python y editor de scripts
2. Macros del proyecto
¿Dónde usar Python en QGIS?
Curso de introducción a PyQGIS
Macros del proyecto
Fuente: https://definicion.de/macro/
"[...] secuencia de instrucciones almacenadas para posibilitar la ejecución organizada de una orden. Esto quiere decir que una macroinstrucción permite que una única orden desencadene una secuencia de varias instrucciones.
...
[...] Es posible almacenar una macro en el propio software en el que se ejecuta, ya sea mediante un botón o una cierta combinación de teclas."
Curso de introducción a PyQGIS
Macros del proyecto
openProject() saveProject() closeProject()
Curso de introducción a PyQGIS
Macros del proyecto: openProject()
Cuando se abra este proyecto... abrir la consola de Python!
Curso de introducción a PyQGIS
Macros del proyecto (discusión)
¿Otros casos de uso?
openProject() saveProject() closeProject()
¿Y si quiero una acción para todos mis proyectos?
Curso de introducción a PyQGIS
Script startup.py
Script para ejecutar código Python cada vez que inicia QGIS.
¿Dónde guardar el script?
/home/USER/.local/share/QGIS/QGIS3/
startup.py
C:\Users\USER\AppData\Roaming\QGIS\QGIS3\
Curso de introducción a PyQGIS
Script startup.py: Ejemplo 1
import qgis
from console import console
def open_console():
if not console._console:
# Initialize the console (QGIS knows how)
qgis.utils.iface.actionShowPythonDialog().trigger()
console._console.setVisible(True)
qgis.utils.iface.initializationCompleted.connect(open_console)
Curso de introducción a PyQGIS
Siempre que se inicie QGIS... abrir la consola de Python
Script startup.py: Ejemplo 2
from qgis.utils import iface
from console import console
if not console._console:
# We need to initialize the console (QGIS knows how)
# and respect the opened/closed state from last session
iface.actionShowPythonDialog().trigger()
console._console.setVisible(console._console.isUserVisible())
console._console.console.shell.runcode("""
L = None
def clc(layer):
global L
L = layer
iface.currentLayerChanged.connect(clc)
""")
console._console.console.shellOut.clearConsole()
Curso de introducción a PyQGIS
Siempre que se inicie QGIS...
enlazar variable "L" con la capa activa
¿Dónde usar Python en QGIS?
1. Consola de Python y editor de scripts
2. Macros del proyecto
3. Acciones
Curso de introducción a PyQGIS
Acciones
Capa
Feature (objeto)
Lienzo (mapa)
Campo
Curso de introducción a PyQGIS
Acciones: Ejemplo 1, Wikipedia
Curso de introducción a PyQGIS
Acciones: Ejemplo 2, mismo valor
Curso de introducción a PyQGIS
Acciones: Ejemplo 3, Export to GPX
3ra Jornada de Talleres Internos
Curso de introducción a PyQGIS
1. Consola de Python y editor de scripts
2. Macros del proyecto
3. Acciones
4. Expresiones personalizadas en Python
¿Dónde usar Python en QGIS?
Curso de introducción a PyQGIS
Buena forma de automatizar en QGIS... ¡sin programar!
Conjunto de funciones disponibles para seleccionar, filtrar, combinar, formatear, convertir, calcular, ..., y agregar valores en QGIS.
Hay condicionales y también variables globales, del proyecto, de la capa, del usuario, etc.
¡Están por todos lados en QGIS!
A veces (muy pocas veces) NO encontramos la que necesitamos.
¡Pero podemos crear nuestras propias funciones... con Python!
Expresiones
Curso de introducción a PyQGIS
Editor de funciones
Expresiones personalizadas
Diálogo de expresiones --> Editor de Funciones
Curso de introducción a PyQGIS
Ejemplo: Dado un punto, obtener su valor de altura desde DEM
Expresiones personalizadas
from qgis.core import (qgsfunction, QgsProject, QgsRaster)
@qgsfunction(args='auto', group='Custom', usesgeometry=True)
def get_elevation(feature, parent):
layers = QgsProject.instance().mapLayersByName("DEM")
if layers: # Any layer called DEM?
rLayer = layers[0]
geom = feature.geometry()
geom.convertToSingleType() # Single points are required
ident = rLayer.dataProvider().identify(geom.asPoint(),
QgsRaster.IdentifyFormatValue)
if ident.isValid():
return ident.results()[1] # Read from band 1
return NULL
raster_value('DEM', 1, $geometry)
Tiempo después...
Curso de introducción a PyQGIS
Ejemplo 2: Obtener un código QR
(usado para los certificados de QGIS Colombia)
Expresiones personalizadas
from qgis.core import (QgsProject, NULL, qgsfunction)
@qgsfunction(args='auto', group='Custom')
def qr(evento, taller, cc, feature, parent):
if evento and taller and cc:
import os, qrcode
base_dir = QgsProject.instance().fileInfo().path()
qr_dir = os.path.join(base_dir, "qr")
filename = "{}-{}-{}".format(evento, taller, cc.replace('.',).replace("'",))
url = "http://qgisusers.co/media/{}.pdf".format(filename)
if not os.path.exists(qr_dir):
os.makedirs(qr_dir)
filepath = os.path.join(qr_dir, "qr-{}.png".format(filename))
qr = qrcode.QRCode(box_size=10,border=2)
qr.add_data(url)
qr.make(fit=True)
img = qr.make_image()
img.save(filepath)
return filepath
else:
return NULL
Curso de introducción a PyQGIS
1. Consola de Python y editor de scripts
2. Macros del proyecto
3. Acciones
4. Expresiones personalizadas en Python
5. Algoritmos de Geoprocesamiento
¿Dónde usar Python en QGIS?
Curso de introducción a PyQGIS
En C++ o en Python.
Usando Python tenemos 2 opciones: clases o decoradores.
Reciben entradas (capas, números, etc.) y retornan salidas.
Escribimos metadatos y QGIS crea el diálogo automáticamente.
Útiles para reusarlos en modelos complejos, mezclando algoritmos incluso de otros proveedores.
Algoritmos de geoprocesamiento
Curso de introducción a PyQGIS
Recursos y documentación
QGIS docs:
https://docs.qgis.org/latest/en/docs/user_manual/processing/scripts.html
Definiendo parámetros de entrada:
https://api.qgis.org/api/master/classQgsProcessingParameterDefinition.html
Definiendo parámetros de salida:
https://api.qgis.org/api/master/classQgsProcessingOutputDefinition.html
Leyendo parámetros:
https://api.qgis.org/api/master/classQgsProcessingAlgorithm.html
¡Otros scripts!
Curso de introducción a PyQGIS
Widgets
Processing agrega widgets dependiendo del tipo de entrada
que elijamos...
Curso de introducción a PyQGIS
Nota: Los scripts con decoradores no pueden ser agregados a proveedores
personalizados. Esto implica que no pueden instalarse desde plugins.
Scripts con decoradores
from qgis.processing import alg
@alg(name='my_script', label='Rename field from vector layer',
group='examplescripts', group_label='Example scripts')
# 'INPUT' is the recommended name for the main input parameter
@alg.input(type=alg.VECTOR_LAYER, name='INPUT', label='Input vector layer')
# 'OUTPUT' is the recommended name for the main output parameter
@alg.output(type=alg.VECTOR_LAYER, name='OUTPUT',
label='Vector layer with renamed field')
def my_script(instance, parameters, context, feedback, inputs):
...
Decoradores: "Syntactic sugar". Actúan sobre métodos y/o clases.
Curso de introducción a PyQGIS
Escribamos un
script de geoprocesamiento
con decoradores...
Ejemplo: Renombrar un campo
Entradas:
Vector layer
Campo a renombrar
Nombre nuevo para el campo
Salidas:
Vector layer
Curso de introducción a PyQGIS
Salidas
Opciones de salida para capas vectoriales:
Modificar la capa de entrada y retornarla
Ver ejemplo anterior (rename field)
Crear una capa nueva y retornarla (capa original intacta)
Para ello se usan los Feature Sink
Curso de introducción a PyQGIS
Reusando scripts en modelos
Curso de introducción a PyQGIS
1. Consola de Python y editor de scripts
2. Macros del proyecto
3. Acciones
4. Expresiones personalizadas en Python
5. Algoritmos de Geoprocesamiento
6. Plugins
¿Dónde usar Python en QGIS?
Curso de introducción a PyQGIS
Escribamos un ejemplo de P.O.O.
Curso de introducción a PyQGIS
Más de PyQt5
Curso de introducción a PyQGIS
Recursos y documentación
Qt5 (C++):
PyQt5:
https://www.riverbankcomputing.com/static/Docs/PyQt5/module_index.html
PyQt5 examples:
https://github.com/pyqt/examples
Curso de introducción a PyQGIS
Principales módulos de PyQt5
Core
GUI
Widgets
qgis.PyQt.QtCore
qgis.PyQt.QtGui
qgis.PyQt.QtWidgets
Funcionalidad núcleo no gráfica.
QObject, QFile, QSettings, QRegExp, SIGNALS-SLOTS...
Funcionalidad núcleo gráfica.
QIcon, QColor, QFont, QCursor, QMouseEvent...
Controles gráficos de usuario para interfaces.
QWidget, QDialog, QPushButton, QMessageBox, QMenu...
Curso de introducción a PyQGIS
Qt-Designer
Aplicación para
diseñar
interfaces
gráficas de Qt
Genera archivos
.ui (XML)
Permite:
+ Definir propiedades de los widgets.
+ Agrupar widgets en layouts.
+ Usar widgets propios de QGIS (custom widgets)
+ Administrar recursos (archivos externos, ej. íconos).
Curso de introducción a PyQGIS
Widgets de Qt
Curso de introducción a PyQGIS
Layouts
Agrupan y organizan
widgets en una interfaz
Layouts más usados:
Horizontal/Vertical
Grid
Form
Curso de introducción a PyQGIS
QGIS custom widgets
Curso de introducción a PyQGIS
SIGNALS-SLOTS
Comunicación
entre objetos de Qt.
Los objetos no se conocen entre sí.
(Bajo acoplamiento)
Los objetos emiten señales, no saben si
alguien las recibe o no. (Encapsulamiento)
SIGNALS
Se emiten cuando ocurre un evento.
Objetos de Qt tienen SIGNALS predefinidas.
Podemos crear nuevas SIGNALS y emitirlas.
SLOTS
Función llamada en respuesta a una SIGNAL.
Objetos de Qt tienen SLOTS predefinidos.
Podemos crear nuevos SLOTS.
Curso de introducción a PyQGIS
SIGNALS-SLOTS
Las conexiones SIGNAL-SLOT
las hace el(la) desarrollador(a).
SIGNALS
Pueden conectarse a cero o muchos SLOTS.
Pueden conectarse a otras SIGNALS.
SLOTS
Pueden conectarse a cero o muchas SIGNALS.
Como son funciones, podemos llamarlas.
Más info en: https://doc.qt.io/qt-5/signalsandslots.html
Curso de introducción a PyQGIS
QGIS Plugins
Curso de introducción a PyQGIS
Copialina...
Curso de introducción a PyQGIS
Arquitectura de los plugins de QGIS
Curso de introducción a PyQGIS
Funciones de los plugins de QGIS
__init__(iface)
initGUI()
unload()
run()
Crear GUI del plugin en QGIS (¿toolbar?, ¿menú?).
Definir conexiones SIGNAL-SLOT.
Remover GUI del plugin (toolbars, menús, etc.) de QGIS.
Desconectar SIGNAL-SLOTs (si es necesario).
Procesar datos o llamar diálogos del plugin.
(opcional)
Obtener acceso a objeto iface para interactuar con QGIS.
Curso de introducción a PyQGIS
Funciones de los plugins de QGIS
__init__(iface), initGUI(), unload(), run()
¡Veámoslas en acción!
Icon adapted from https://www.iconfinder.com/paomedia
Clic a la imagen :)
Curso de introducción a PyQGIS
Test plugin repo: https://github.com/gacarrillor/test
Plugins para desarrolladores
Plugin reloader
First aid
Plugin builder
(Opcional)
Curso de introducción a PyQGIS
QGIS Minimal Plugin
1. Ve a la carpeta de plugins de QGIS (ver instrucciones).
2. En esa carpeta crea una carpeta llamada "minimal".
3. Ve a https://github.com/wonder-sk/qgis-minimal-plugin
4. Crea los archivos __init__.py y metadata.txt copiando
el contenido del QGIS Minimal Plugin de Martin Dobias.
5. Reinicia QGIS y activa el plugin "Minimal".
Curso de introducción a PyQGIS
Plugin con Diálogo
Extendamos el Minimal Plugin...
Curso de introducción a PyQGIS
Plugin con QGIS Custom Widgets
Extendamos el plugin con diálogo...
Curso de introducción a PyQGIS
Plugin Spatial Join (demo)
Un plugin un poco más completo...
Curso de introducción a PyQGIS
1. Consola de Python y editor de scripts
2. Macros del proyecto
3. Acciones
4. Expresiones personalizadas en Python
5. Algoritmos de Geoprocesamiento
6. Plugins
7. Scripts 'standalone' (sin la GUI de QGIS)
¿Dónde usar Python en QGIS?
Curso de introducción a PyQGIS
Casos de uso de scripts standalone
Se busca generar productos diarios/semanales/mensuales (vectores, rásters, mapas, reportes, estadísticas) a partir de una BD que se alimenta con frecuencia.
Se busca ejecutar periódicamente un ETL, obteniendo datos de diferentes servicios web de fuentes oficiales para almacenarlos en una BD local.
Una entidad oficial obtiene datos de terceros mediante formulario web y quiere hacer una validación de calidad automática.
Curso de introducción a PyQGIS
Configuración scripts standalone
Windows
GNU/Linux
Open OSGeo4w Shell --> Run python-qgis-ltr.bat
Prepare environment with PYTHONPATH and LD_LIBRARY_PATH.
export PYTHONPATH=/path/to/qgis/output/python/
export LD_LIBRARY_PATH=/path/to/qgis/lib/
Curso de introducción a PyQGIS
¡Cuidado!
¡No tenemos iface!
Curso de introducción a PyQGIS
Script standalone 1: Layer info
from qgis.core import (QgsApplication, QgsVectorLayer)
# Details about the prefix: https://gis.stackexchange.com/a/155852/4972
# Hint: print(QgsApplication.showSettings())
QgsApplication.setPrefixPath("/docs/dev/qgis/QGIS/3_14_0/output/", True)
qgs = QgsApplication([], False) # No GUI
qgs.initQgis()
airport_layer = QgsVectorLayer("/path/to/data.gpkg|layername=Airports",
"airport",
"ogr")
print("Layer name:", airport_layer.name())
print("Layer is valid:", airport_layer.isValid())
qgs.exit()
Curso de introducción a PyQGIS
Script standalone 2: Run algorithm
# Source: https://gis.stackexchange.com/a/279937/4972
import sys
from qgis.core import QgsApplication
from qgis.analysis import QgsNativeAlgorithms
QgsApplication.setPrefixPath('/docs/dev/qgis/QGIS/3_14_0/output', True)
qgs = QgsApplication([], False)
qgs.initQgis()
# Append the path where processing plugin can be found
sys.path.append('/docs/dev/qgis/QGIS/3_14_0/output/python/plugins')
import processing
from processing.core.Processing import Processing
Processing.initialize()
QgsApplication.processingRegistry().addProvider(QgsNativeAlgorithms())
params = {'POLYGONS':'/path/to/polygons.gpkg',
'LINES':'/path/to/lines.gpkg',
'LEN_FIELD':'LENGTH',
'COUNT_FIELD':'COUNT',
'OUTPUT':'TEMPORARY_OUTPUT'}
res = processing.run("native:sumlinelengths", params)
for feature in res['OUTPUT'].getFeatures():
print(feature['name'], feature['LENGTH'])
qgs.exit()
Curso de introducción a PyQGIS
Out of topic: qgis_process
$ qgis_process run native:sumlinelengths
--POLYGONS="/path/to/polygons.gpkg"
--LINES="/path/to/lines.gpkg"
--LEN_FIELD=LENGTH
--COUNT_FIELD=COUNT
--OUTPUT=/tmp/gpkg/output_sum.gpkg
Curso de introducción a PyQGIS
¿Ves alguna diferencia?
Hay otros escenarios en donde puedes usar Python con QGIS:
Otros escenarios (avanzados)
Aplicaciones gráficas standalone Plugins de QGIS Server
Fuente: Plugin QGIS Server y roles
Fuente: Visor de PyQGIS
Curso de introducción a PyQGIS
PyQGIS samples:
https://github.com/webgeodatavore/pyqgis-samples
Victor Olaya's QGIS Python Course:
https://github.com/volaya/qgis-python-course
Diagrama de clases PyQGIS (cuidado, es para QGIS v2!):
https://labs.webgeodatavore.com/partage/diagramme_principal.html
PyQGIS in a day:
https://courses.spatialthoughts.com/pyqgis-in-a-day.html
Curso PyQGIS 3 impartido junto a M. Kuhn en Colombia:
Otros enlaces de interés...
Curso de introducción a PyQGIS
¡Ahora sigues tú!
Eso es todo...
Eso no es todo...
Curso de introducción a PyQGIS
Introducción al desarrollo con PyQGIS
By germap
Introducción al desarrollo con PyQGIS
Curso-taller ofrecido a QGIS Colombia
- 2,634