Exercice 6 : Automatisation d’actions répétitives

_images/ex4_osm.png

Objectif

Cet exercice a pour objectif de montrer l’intérêt de la console Python pour automatiser des actions répétitives.

Données

malta-latest.shp.zip : Données OpenStreetMap (transformées en Shapefile par GeoFabrik) pour Malte [1]Téléchargement
StylesQgisOsm.zip : Une collection de styles QGIS pour données OSM [2]Téléchargement

Problème

Lors de la décompression de l’archive malta-latest.shp.zip on peut constater que de nombreux fichiers sont extraits (16 couches). Seules 11 d’entres elles vont nous être utile.

Pour appliquer les styles téléchargés, en l’absence de projet .qgs nous devrons effectuer les étapes suivantes.
  • charger les différentes couches nécessaires,

  • appliquer le style téléchargé (par exemple : double-click sur la couche gis_osm_water_a_free_1.shp pour ouvrir les propriétés de style, puis click sur Style .. > Charger style .. et sélection du style ayant le nom gis_osm_water_a_free_1.qml),

  • … en faisant attention à l’ordre des couches !

  • … et en répétant l’opération pour chacune des couches !

_images/ex4_consignes_GH.png

Exemple d’instructions trouvées sur internet (1)

_images/ex4_consignes_GH2.png

Exemple d’instructions trouvées sur internet (2)

N’étant pas satisfait par les propriétés de transparence, nous verrons comment la changer sur toutes les couches qui contiennent des polygones.

On va tout effectuer en Python pour voir le gain de temps que ça peut représenter.

Procédure

  • Décompresser l’archive “StylesQgisOsm.zip” dans un dossier de votre choix (“exercice4” par exemple). L’archive contenant les couches de données sera à décompresser en Python.

  • Ouvrir QGIS.

  • Ouvrir la console Python (les fichiers seront extraits de l’archive et ajoutés à la carte en Python).

  • Lire les rappels et les nouveaux éléments qui suivent :.

    • Rappel concernant les dossiers en Python :

      # On accède à la majorité des fonctions relatives à la navigation
      # dans l'arborescence du système de fichier à part du module 'os'
      import os
      
      # Connaitre le dossier actuel de travail
      os.getcwd() # getcwd -> get current working directory
      
      # Se rendre dans le dossier approprié (attention à le modifier)
      os.chdir('exercice4')
      
      # Lister le contenu d'un dossier (ici le dossier 'Styles')
      os.listdir('Styles') # On utilise '.' pour le dossier actuel
      
    • On peut ainsi effectuer des opérations de filtrage lors du listage du dossier

      # Lister les fichiers d'un type particulier au sein d'un dossier
      # en utilisant une liste de compréhension
      names_svg = \
          [name for name in os.listdir('/home/mthh/Images') if '.svg' in name]
      
    • Rappel sur les chaines de caractères

      # Remplacer/supprimer une sous-chaine de caractères :
      name = 'filename.svg'
      name.replace('.svg', '')  # 'filename'
      name.replace('.svg', '.png')  # 'filename.png'
      
    • Extraire une archive .zip dans le dossier courant depuis l’interpréteur Python :

      import zipfile
      
      zip_ref = zipfile.ZipFile('malta-latest-free.shp.zip', 'r')
      zip_ref.extractall('.')
      zip_ref.close()
      
    • Nouvelles notions en PyQgis concernant l’interface (QgisInterface) ou le projet (QgsProject) en cours :

      # Obtenir une référence au projet en cours :
      project = QgsProject.instance()
      
      # Enlever les couches existantes dans le projet actuel :
      project.clear()
      
      # Zoomer la carte sur une couche (ici sur la couche active) :
      layer = iface.activeLayer()
      canvas = iface.mapCanvas()
      canvas.setExtent(layer.extent())
      canvas.refresh()
      
      # Changer l'étendue du canvas en utilisant
      # des coordonnées xmin, ymin, xmax, ymax :
      rect = QgsRectangle(QgsRectangle(1599940, 4284653, 1617650, 4284653))
      iface.mapCanvas().setExtent(rect)
      iface.mapCanvas().refresh()
      
      # Régler la projection du projet sur "Web-Mercator" :
      project.setCrs(QgsCoordinateReferenceSystem('EPSG:3857'))
      iface.mapCanvas().refresh()
      
    • Nouvelles notions en PyQgis concernant les couches vecteurs (QgsVectorLayer)

      # Ajouter une couche :
      layer = iface.addVectorLayer('path/to/layer.shp', name, 'ogr')
      
      # Charger un style et le lui appliquer :
      layer.loadNamedStyle('path/to/style.qml')
      layer.triggerRepaint()
      
      # Si on ajoute plusieurs couches à la suite et que la mise en cache
      # n'est pas active on évitera d'appeler la méthode 'triggerRepaint'
      # sur chaque couche et on préférera rafraichir
      # l'ensemble du canvas une fois l'opération terminée :
      if iface.mapCanvas().isCachingEnabled():
          layer.triggerRepaint()
      else:
          iface.mapCanvas().refresh()
      
  • À vous de jouer ! En utilisant les éléments vu au-dessus, écrivez un script permettant de :

    • se rendre dans le dossier dans lequel vous avez décompresser la première archive,

    • y dézipper la seconde (malta-latest.shp.zip) dans le même dossier,

    • lister les styles disponibles (fichiers .qml dans le dossier Styles),

    • utiliser leurs noms pour charger les fichiers Shapefile correspondants,

    • appliquer le style approprié à chacune des couches.

  • Et l’ordre des couches ? Voici l’ordre optimal pour ce projet (la première couche de la liste est celle qui doit apparaître au-dessus de toutes les autres à l’affichage, c’est le même ordre que dans le panneau de gestion des couches de QGIS). Utiliser cette variable pour obtenir l’ordre souhaité dans votre projet !

    À vous de jouer ! (La cheatsheet de ce TP, un moteur de recherche et/ou la documentation PyQgis seront utiles)

    ordre = [
        'gis_osm_traffic_a_free_1',
        'gis_osm_pofw_a_free_1',
        'gis_osm_places_free_1',
        'gis_osm_natural_free_1',
        'gis_osm_roads_free_1',
        'gis_osm_buildings_a_free_1',
        'gis_osm_pois_a_free_1',
        'gis_osm_water_a_free_1',
        'gis_osm_waterways_free_1',
        'gis_osm_landuse_a_free_1',
        'gis_osm_natural_a_free_1',
        ]
    
  • Nous devons maintenant régler l’opacité de chacune des couches de type Polygon à 90%.

    À vous de jouer ! (La cheatsheet de ce TP, un moteur de recherche et/ou la documentation PyQgis seront utiles)

Sauvegarder votre projet

  • Il est nécessaire de récupérer une référence au projet actuel :

    project = QgsProject.instance()
    # Attention au chemin du fichier que vous sauvegardez !
    project.write('osm_malta.qgs')
    

Autres exemples d’utilisation du Python dans QGIS

Qu’en est-il des actions qu’il pourrait être nécessaire d’effectuer à chaque ouverture d’un projet spécifique ? Il est possible de définir des fonctions Python qui seront appelées à l’ouverture, à l’enregistrement ou à la fermeture d’un projet.

_images/ex4_macros.png
  • Nous souhaitons par exemple afficher un message d’avertissement à l’ouverture d’un projet :

    def openProject():
        msg_bar = iface.messageBar()
        msg_bar.pushMessage(
          'WARNING', # Le titre du message
          'Le projet contient des données sensibles.', # Son contenu
          Qgis.WARNING, # Le type de message
          15, # Le délai d'affichage
        )
    

Footnotes