Um requisito comum no GIS é aplicar uma ferramenta de processamento a vários arquivos ou aplicar um processo a vários recursos de um arquivo a outro arquivo.
Muitas dessas operações são embaraçosamente paralelas, pois os resultados dos cálculos não influenciam em nenhuma outra operação do loop. Não apenas isso, mas frequentemente os arquivos de entrada são distintos.
Um exemplo clássico é o agrupamento de arquivos de forma contra arquivos que contêm polígonos para prendê-los.
Aqui está um método processual clássico (testado) para conseguir isso em um script python para QGIS. (fyi a saída de arquivos de memória temporários para arquivos reais mais da metade do tempo para processar meus arquivos de teste)
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())
Isso seria bom, exceto que meu arquivo de entrada tem 2 GB e o arquivo de recorte de polígono contém mais de 400 polígonos. O processo resultante leva mais de uma semana na minha máquina quad core. Enquanto isso, três núcleos estão ociosos.
A solução que tenho em minha cabeça é exportar o processo para arquivos de script e executá-los de forma assíncrona usando o gnu paralelo, por exemplo. No entanto, parece uma pena ter que abandonar o QGIS em uma solução específica do SO, em vez de usar algo nativo do python do QGIS. Então, minha pergunta é:
Posso paralelizar operações geográficas embaraçosamente paralelas nativamente dentro do python QGIS?
Caso contrário, talvez alguém já tenha o código para enviar esse tipo de trabalho para scripts shell assíncronos?