Ejecutar y Programar Trabajos de Procesamiento QGIS

Puede automatizar bastantes tareas en QGIS usando scripts de Python (PyQGIS) y el Marco de Procesamiento. La mayor parte del tiempo, correría estos scripts manualmente mientras QGIS está abierto. Mientras esto es útil, varias veces necesitará ejecutar estas tareas mediante la línea de comando y sin necesidad de abrir QGIS. Afortunadamente, puede escribir scripts python independientes que usan bibliotecas QGIS y pueden correr mediante la línea de comando. En este tutorial, aprenderemos como escribir y programar una tarea que usa el Marco de Procesamiento QGIS.

Vista general de la tarea

Digamos que estamos trabajando en algún análisis usando archivos shape de una región. Los archivos shape están actualizados diariamente y siempre necesitamos el último archivo. Pero antes que podamos usar estos archivos, necesitamos limpiar los datos. Podemos establecer un trabajo QGIS que automatice este proceso y se ejecute diariamente de manera que tenga los últimos archivos shape limpiados para su trabajo. Escribiremos un script Python autónomo que descarga un archivo shape y ejecuta operaciones de limpieza topológica diariamente.

Otras habilidades que aprenderá

  • Descarga y descompresión de archivos usando Python

  • Ejecutar cualquier algoritmo de Procesamiento mediante PyQGIS.

  • Corregir errores topológicos en una capa vectorial.

Obtener los datos

Geofabrik provee archivos shape actualizados diariamente de conjuntos de datos OpenStreetMap.

Usaremos archivos shape para Fiji en este ejercicio. Descargue fiji-latest.shp.zip y descomprímalo en una carpeta de su disco.

Fuente de Datos [GEOFABRIK]

Procedimiento

  1. Primero pasaremos por el proceso de limpiar manualmente el archivo shape para anotar los comandos que usaremos en el script python. Inicie QGIS y vaya a Capa ‣ Añadir Capa ‣ Añadir Capa Vectorial.

../_images/1280.png
  1. Explore la carpeta que contiene los archivos shape descomprimidos y seleccione el archivo roads.shp y clic en Abrir.

../_images/2182.png
  1. Primero debemos reproyectar la capa caminos a un SRC Proyectado. Esto nos permitirá usar metros como unidades cuando se realice el análisis en vez de grados. Abra Procesos ‣ Caja de Herramientas.

../_images/3125.png
  1. Busque la herramienta Reproyectar capa. Doble-clic en ella para iniciar el diálogo.

../_images/479.png
  1. En el diálogo Reproyectar Capa, seleccione la capa roads como nuestra Capa de Entrada. Usaremos el SRC EPSG:3460 Fiji 1986 / Fiji Map Grid como el SRC Destino. Clic en Ejecutar.

../_images/573.png
  1. Una vez que termine el proceso, verá la capa reproyectada cargada en QGIS. Vaya a Procesos ‣ Historia y Registro...

../_images/670.png
  1. En diálogo Historia y Registro, expanda la carpeta Algoritmo y seleccione la última entrada. Verá mostrado el comando completo de procesamiento en el panel de abajo. Anote este comando para usarlo en nuestro script.

../_images/769.png
  1. De vuelta en la ventana principal de QGIS, clic en el botón SRC en la esquina inferior derecha.

../_images/867.png
  1. En el diálogo Propiedades del Proyecto | SRC, marque la Habilite la transformación SRC al vuelo y seleccione EPSG:3460 Fiji 1986 / Fiji Map Grid como el SRC. Esto asegurará que nuestras capas originales y reproyectadas se alineen correctamente.

../_images/966.png
  1. Ahora ejecutaremos la operación de limpieza. GRASS tiene un conjunto muy poderoso de herramienta de limpieza topológica. Éstas están disponible en QGIS mediante el algoritmo v.clean. Busque este algoritmo en la Caja de Herramientas de Procesos y doble-clic en ella para iniciar el diálogo.

../_images/1074.png
  1. Puede leer más acerca de las varias herramientas y opciones en la pestaña Ayuda. Para este tutorial, estaremos usando la herramienta autoajuste para eliminar vértices duplicados que están a 1 metro de distancia uno del otro. Seleccione Capa reproyectada como la Capa a limpiar. Elija autoajuste como la Herramienta de limpieza. Ingrese 1.00 como el Umbral. Deje los otros campos en blanco y clic Ejecutar.

../_images/11112.png
  1. Una vez que termine el procesamiento, verá 2 capas nuevas agregadas a QGIS. La Capa vectorial limpiada es la capa con errores topológicos corregidos. También tendrá una Capa de errores que destaca los elementos espaciales que fueron reparados. Puede usar la capa de errores como una guía y acercarse para ver los vértices que fueron eliminados.

../_images/1281.png
  1. Vaya al diálogo Procesos ‣ Historia y Registro y anote el comando completo de procesamiento para uso posterior.

../_images/1372.png
  1. Ahora estamos listos para iniciar la codificación. Vea la sección Un Editor de Texto o un IDE Python en el tutorial Construir una extension Python para instrucciones para establecer su editor de texto o IDE. Para ejecutar scripts python autónomos que usen QGIS, debemos establecer varias opciones de configuración. Una buena manera de ejecutar scripts autónomos es iniciarlos mediante un archivo .bat. Este archivo establecerá primero las opciones de configuración y luego llamará al script de python. Cree un nuevo archivo llamado launch.bat e ingrese el siguiente texto. Cambie los valores de acuerdo a su configuración QGIS. No olvide reemplazar el nombre de usuario con el suyo en la ruta al script python. Las rutas en este archivo serán las mismas en su sistema si ha instalado QGIS mediante el instalador OSGeo4W. Guarde el archivo en su Escritorio.

Nota

Los usuarios Linux y Mac necesitarán crear un script shell para establecer las rutas y variables de entorno.

REM Change OSGEO4W_ROOT to point to the base install folder
SET OSGEO4W_ROOT=C:\OSGeo4W64
SET QGISNAME=qgis
SET QGIS=%OSGEO4W_ROOT%\apps\%QGISNAME%
set QGIS_PREFIX_PATH=%QGIS%
REM Gdal Setup
set GDAL_DATA=%OSGEO4W_ROOT%\share\gdal\
REM Python Setup
set PATH=%OSGEO4W_ROOT%\bin;%QGIS%\bin;%PATH%
SET PYTHONHOME=%OSGEO4W_ROOT%\apps\Python27
set PYTHONPATH=%QGIS%\python;%PYTHONPATH%

REM Launch python job
python c:\Users\Ujaval\Desktop\download_and_clean.py
pause
../_images/1468.png
  1. Cree un nuevo archivo python e ingrese el siguiente código. Nombre el archivo como download_and_clean.py y guárdelo en su Escritorio.

from qgis.core import *
print 'Hello QGIS!'
../_images/1561.png
  1. Cámbiese a su Escritorio y localice el icono launch.bat. Haga doble-clic para iniciar una nueva ventana de comando y ejecutar el script. Si ve una Hola QGIS! impreso en la ventana de comando, su configuración funcionó bien. Si ve errores, o no ve el texto, revise su archivo launch.bat y asegúrese que todas las rutas coinciden con las ubicaciones en su sistema.

../_images/1658.png
  1. De vuelta en su editor de texto, modifique el script download_and_clean.py para agregar el siguiente código. Este es el código de arranque para inicializar QGIS. Esto es innecesario si está ejecutando el script dentro de QGIS. Pero debido a que lo estamos ejecutándolo de fuera de QGIS, necesitamos agregarlos al inicio. Asegúrese de reemplazar el nombre de usuario con el suyo. Después de hacer estos campos, guarde el archivo y ejecute de nuevo launch.bat. Si ve impreso Hola QGIS!, está listo para agregar la lógica de procesamiento al script.

import sys
from qgis.core import *

# Initialize QGIS Application
QgsApplication.setPrefixPath("C:\\OSGeo4W64\\apps\\qgis", True)
app = QgsApplication([], True)
QgsApplication.initQgis()

# Add the path to Processing framework
sys.path.append('c:\\Users\\Ujaval\\.qgis2\\python\\plugins')

# Import and initialize Processing framework
from processing.core.Processing import Processing
Processing.initialize()
import processing

print 'Hello QGIS!'
../_images/1755.png
  1. Recupere el primer comando de procesamiento que guardamos de la bitácora. Este era el comando para reproyectar una capa. Pegue el comando a su script y agregue el código que le rodea que sigue. Note que los comandos de procesamiento devuelven la ruta a las capas de salida como una diccionario. Estamos almacenando esto como el valor ret e imprimiendo la ruta a la capa reproyectada.

roads_shp_path = "C:\\Users\\Ujaval\\Downloads\\fiji-latest.shp\\roads.shp"
ret = processing.runalg('qgis:reprojectlayer', roads_shp_path, 'EPSG:3460',
None)
output = ret['OUTPUT']
print output
../_images/1851.png
  1. Ejecute el script mediante launch.bat y verá la ruta a la capa reproyectada recién creada.

../_images/1942.png
  1. Ahora agregue el código para la limpieza de topología. Debido a que esta es nuestra salida final, agregaremos las rutas de archivos de salida como los últimos 2 argumentos para el algoritmo grass.v.clean. Si dejó vacíos estos, la salida será creada en un directorio temporal.

processing.runalg("grass:v.clean",
                  output,
                  1,
                  1,
                  None,
                  -1,
                  0.0001,
                  'C:\\Users\\Ujaval\\Desktop\\clean.shp',
                  'C:\Users\\Ujaval\\Desktop\\errors.shp')
../_images/2037.png
  1. Ejecute el script y verá 2 nuevos archivos shape creados en su Escritorio. Esto completa la parte de procesamiento del script. Agreguemos el código para descargar los datos del sitio web original y para descomprimirlos automáticamente. También almacenaremos la ruta al archivo descomprimido en una variable que podemos pasar después al algoritmo de procesamiento. Necesitaremos importar algunos módulos adicionales para hacer esto. (Vea el final del tutorial para el script completo con todos los cambios)

import os
import urllib
import zipfile
import tempfile

temp_dir = tempfile.mkdtemp()
download_url = 'http://download.geofabrik.de/australia-oceania/fiji-latest.shp.zip'
print 'Downloading file'
zip, headers = urllib.urlretrieve(download_url)
with zipfile.ZipFile(zip) as zf:
    files = zf.namelist()
    for filename in files:
        if 'roads' in filename:
            file_path = os.path.join(temp_dir, filename)
            f = open(file_path, 'wb')
            f.write(zf.read(filename))
            f.close()
            if filename == 'roads.shp':
                roads_shp_path = file_path
../_images/2183.png
  1. Ejecute el script completado. Cada vez que ejecuta el script, se descargará y procesará una copia fresca de los datos.

../_images/2235.png
  1. Para automatizar la ejecución diaria de este script, podemos usar el Programador de Tarea en Windows. Inicie el Programador de Tarea y clic en Crear Tarea Básica.

Nota

Los usuarios de Linux y Mac pueden usar tareas cron para programar tareas.

../_images/2332.png
  1. Nombre la tarea como Descarga y Limpieza Diaria y clic en Siguiente.

../_images/2431.png
  1. Seleccione Diariamente como el Disparador y clic en Siguiente

../_images/2528.png
  1. Seleccione una hora a su gusto y clic en Siguiente.

../_images/2625.png
  1. Escoja Iniciar un programa como la Acción y clic en Siguiente.

../_images/2725.png
  1. Clic Explorar y localice el script launch.bat. Clic en Siguiente.

../_images/2824.png
  1. Clic Finalizar en la última pantalla para programar la tarea. Ahora el script se iniciará automáticamente cada día en la hora especificada para darle una copia fresca de los datos limpiados.

../_images/2921.png

Abajo está el script download_and_clean.py completo para su referencia.

import sys
from qgis.core import *

import os
import urllib
import zipfile
import tempfile

# Initialize QGIS Application
QgsApplication.setPrefixPath("C:\\OSGeo4W64\\apps\\qgis", True)
app = QgsApplication([], True)
QgsApplication.initQgis()

# Add the path to Processing framework  
sys.path.append('c:\\Users\\Ujaval\\.qgis2\\python\\plugins')

# Import and initialize Processing framework
from processing.core.Processing import Processing
Processing.initialize()
import processing

# Download and unzip the latest shapefile
temp_dir = tempfile.mkdtemp()
download_url = 'http://download.geofabrik.de/australia-oceania/fiji-latest.shp.zip'
print 'Downloading file'
zip, headers = urllib.urlretrieve(download_url)
with zipfile.ZipFile(zip) as zf:
    files = zf.namelist()
    for filename in files:
        if 'roads' in filename:
            file_path = os.path.join(temp_dir, filename)
            f = open(file_path, 'wb')
            f.write(zf.read(filename))
            f.close()
            if filename == 'roads.shp':
                roads_shp_path = file_path

print 'Downloaded file to %s' % roads_shp_path

# Reproject the Roads layer
print 'Reprojecting the roads layer'

ret = processing.runalg('qgis:reprojectlayer', roads_shp_path, 'EPSG:3460', None)
output = ret['OUTPUT']

# Clean the Roads layer
print 'Cleaning the roads layer'

processing.runalg("grass:v.clean",
                  output,
                  1,
                  1,
                  None,
                  -1,
                  0.0001,
                  'C:\\Users\\Ujaval\\Desktop\\clean.shp',
                  'C:\Users\\Ujaval\\Desktop\\errors.shp')
print 'Success'

If you want to give feedback or share your experience with this tutorial, please comment below. (requires GitHub account)