Un requisito común en los SIG es aplicar una herramienta de procesamiento a varios archivos o aplicar un proceso para una serie de características de un archivo a otro.
Muchas de estas operaciones son vergonzosamente paralelas en el sentido de que los resultados de los cálculos de ninguna manera influyen en ninguna otra operación en el ciclo. No solo eso, sino que a menudo los archivos de entrada son distintos.
Un ejemplo clásico es la disposición en mosaico de archivos de formas contra archivos que contienen polígonos para recortarlos.
Aquí hay un método de procedimiento clásico (probado) para lograr esto en un script de Python para QGIS. (Para su información, la salida de archivos de memoria temporal a archivos reales más de la mitad del tiempo para procesar mis archivos de prueba)
import processing
import os
input_file="/path/to/input_file.shp"
clip_polygons_file="/path/to/polygon_file.shp"
output_folder="/tmp/test/"
input_layer = QgsVectorLayer(input_file, "input file", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(input_layer)
tile_layer = QgsVectorLayer(clip_polygons_file, "clip_polys", "ogr")
QgsMapLayerRegistry.instance().addMapLayer(tile_layer)
tile_layer_dp=input_layer.dataProvider()
EPSG_code=int(tile_layer_dp.crs().authid().split(":")[1])
tile_no=0
clipping_polygons = tile_layer.getFeatures()
for clipping_polygon in clipping_polygons:
print "Tile no: "+str(tile_no)
tile_no+=1
geom = clipping_polygon.geometry()
clip_layer=QgsVectorLayer("Polygon?crs=epsg:"+str(EPSG_code)+\
"&field=id:integer&index=yes","clip_polygon", "memory")
clip_layer_dp = clip_layer.dataProvider()
clip_layer.startEditing()
clip_layer_feature = QgsFeature()
clip_layer_feature.setGeometry(geom)
(res, outFeats) = clip_layer_dp.addFeatures([clip_layer_feature])
clip_layer.commitChanges()
clip_file = os.path.join(output_folder,"tile_"+str(tile_no)+".shp")
write_error = QgsVectorFileWriter.writeAsVectorFormat(clip_layer, \
clip_file, "system", \
QgsCoordinateReferenceSystem(EPSG_code), "ESRI Shapefile")
QgsMapLayerRegistry.instance().addMapLayer(clip_layer)
output_file = os.path.join(output_folder,str(tile_no)+".shp")
processing.runalg("qgis:clip", input_file, clip_file, output_file)
QgsMapLayerRegistry.instance().removeMapLayer(clip_layer.id())
Esto estaría bien, excepto que mi archivo de entrada es de 2GB y el archivo de recorte de polígonos contiene más de 400 polígonos. El proceso resultante lleva más de una semana en mi máquina de cuatro núcleos. Mientras tanto, tres núcleos están inactivos.
La solución que tengo en mi cabeza es exportar el proceso a archivos de script y ejecutarlos de forma asíncrona usando gnu paralelo, por ejemplo. Sin embargo, parece una pena tener que abandonar QGIS en una solución específica del sistema operativo en lugar de usar algo nativo de QGIS python. Entonces mi pregunta es:
¿Puedo paralelizar operaciones geográficas embarazosamente paralelas de forma nativa dentro de Python QGIS?
Si no es así, ¿tal vez alguien ya tenga el código para enviar este tipo de trabajo a scripts de shell asíncronos?