Une exigence courante dans le SIG est d'appliquer un outil de traitement à un certain nombre de fichiers ou d'appliquer un processus pour un certain nombre de fonctionnalités d'un fichier à un autre fichier.
La plupart de ces opérations sont parallèlement d'une manière embarrassante en ce sens que les résultats des calculs n'influencent en aucune manière aucune autre opération dans la boucle. Non seulement cela, mais souvent les fichiers d'entrée sont chacun distincts.
Un exemple classique est la mise en mosaïque de fichiers de forme contre des fichiers contenant des polygones pour les couper.
Voici une méthode procédurale classique (testée) pour y parvenir dans un script python pour QGIS. (pour la sortie des fichiers de mémoire temporaire en fichiers réels, le temps de traitement de mes fichiers de test a été réduit de plus de moitié)
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())
Ce serait bien, sauf que mon fichier d'entrée est de 2 Go et que le fichier d'écrêtage de polygone contient plus de 400 polygones. Le processus résultant prend plus d'une semaine sur ma machine quadricœur. Pendant ce temps, trois cœurs tournent au ralenti.
La solution que j'ai dans ma tête est d'exporter le processus vers des fichiers de script et de les exécuter de manière asynchrone en utilisant gnu parallel par exemple. Cependant, il semble dommage de devoir abandonner QGIS dans une solution spécifique au système d'exploitation plutôt que d'utiliser quelque chose de natif pour QGIS python. Ma question est donc:
Puis-je paralléliser des opérations géographiques parallèlement embarrassantes en natif dans python QGIS?
Sinon, alors peut-être que quelqu'un a déjà le code pour envoyer ce genre de travail aux scripts shell asynchrones?