23.7. Utiliser les algorithmes du module de traitements depuis la console Python

La console permet aux utilisateurs confirmés d’accroître leur productivité en réalisant des opérations complexes qui ne pourraient pas être réalisées à partir de l’interface graphique du module de Traitements. Les modèles impliquant plusieurs algorithmes peuvent être définis à partir de l’interface en lignes de commandes et des opérations additionnelles comme les boucles ou les opérations conditionnelles permettent de créer des flux de traitements plus puissants et plus flexibles.

Il n’y a pas de console spécifique au module de traitements de QGIS mais toutes les commandes du module sont disponibles via la console Python de QGIS. Cela signifie que vous pouvez intégrer ces commandes dans votre travail et les connecter aux autres fonctions accessibles depuis la console (dont les méthodes issues de l’API QGIS).

Le code exécuté à partir de la console Python, même s’il n’utilise pas de méthodes de traitements particulières, peut être converti en un nouvel algorithme pour être réutilisé dans la boîte à outils, le modeleur ou dans un autre flux de traitements, comme tout autre algorithme. Ainsi certains algorithmes que vous pouvez trouver dans la boîte à outils sont en fait de simples scripts.

Dans cette section, nous allons voir comme utiliser des algorithmes issus du module de Traitements à partir de la console Python de QGIS et également comment écrire des algorithmes en Python.

23.7.1. Appeler des algorithmes depuis la console Python

La première chose à faire est d’importer les fonctions de traitement à l’aide de l’instruction suivante:

>>> from qgis import processing

A présent, la seule instruction (intéressante) à faire est d’exécuter un algorithme. Cela est effectué en utilisant la méthode run(), qui prend en premier paramètre le nom de l’algorithme à lancer, puis tous les paramètres nécessaires à son exécution. Vous devez donc connaître le nom de commande de l’algorithme, qui peut être différent de celui affiché dans la boîte à outils. Pour le trouver, vous pouvez utiliser processingRegistry en tapant dans la console la commande suivante :

>>> for alg in QgsApplication.processingRegistry().algorithms():
        print(alg.id(), "->", alg.displayName())

Vous obtiendrez quelque chose de ce genre (avec quelques tirets en plus pour la lisibilité).

3d:tessellate --------------> Tessellate
gdal:aspect ----------------> Aspect
gdal:assignprojection ------> Assign projection
gdal:buffervectors ---------> Buffer vectors
gdal:buildvirtualraster ----> Build Virtual Raster
gdal:cliprasterbyextent ----> Clip raster by extent
gdal:cliprasterbymasklayer -> Clip raster by mask layer
gdal:clipvectorbyextent ----> Clip vector by extent
gdal:clipvectorbypolygon ---> Clip vector by mask layer
gdal:colorrelief -----------> Color relief
gdal:contour ---------------> Contour
gdal:convertformat ---------> Convert format
gdal:dissolve --------------> Dissolve
...

Il s’agit là de la liste des identifiants de tous les algorithmes disponibles, triés par le nom du fournisseur puis l’ID de l’algorithme, accompagnés du nom littéral de l’algorithme.

Une fois trouvé le nom de commande de l’algorithme, il s’agit de connaître la bonne syntaxe pour l’exécuter. Cela comprend la liste des paramètres à fournir à l’appel de la méthode run().

Une méthode est destinée à décrire en détail un algorithme et renvoie la liste des paramètres nécessaires et le type de sortie généré. Il s’agit de la méthode algorithmHelp(id_algorithme). Veillez à bien utiliser l’ID de l’algorithme et non le nom descriptif.

En appelant la méthode avec native: buffer comme paramètre ( qgis: buffer est un alias pour native: buffer et fonctionnera également), vous obtenez la description suivante:

>>> processing.algorithmHelp("native:buffer")
Buffer (native:buffer)

This algorithm computes a buffer area for all the features in an
input layer, using a fixed or dynamic distance.

The segments parameter controls the number of line segments to
use to approximate a quarter circle when creating rounded
offsets.

The end cap style parameter controls how line endings are handled
in the buffer.

The join style parameter specifies whether round, miter or
beveled joins should be used when offsetting corners in a line.

The miter limit parameter is only applicable for miter join
styles, and controls the maximum distance from the offset curve
to use when creating a mitered join.


----------------
Input parameters
----------------

INPUT: Input layer

   Parameter type: QgsProcessingParameterFeatureSource

   Accepted data types:
           - str: layer ID
           - str: layer name
           - str: layer source
           - QgsProcessingFeatureSourceDefinition
           - QgsProperty
           - QgsVectorLayer

DISTANCE: Distance

   Parameter type: QgsProcessingParameterDistance

   Accepted data types:
           - int
           - float
           - QgsProperty

SEGMENTS: Segments

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

END_CAP_STYLE: End cap style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Flat
           - 2: Square

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

JOIN_STYLE: Join style

   Parameter type: QgsProcessingParameterEnum

   Available values:
           - 0: Round
           - 1: Miter
           - 2: Bevel

   Accepted data types:
           - int
           - str: as string representation of int, e.g. '1'
           - QgsProperty

MITER_LIMIT: Miter limit

   Parameter type: QgsProcessingParameterNumber

   Accepted data types:
           - int
           - float
           - QgsProperty

DISSOLVE: Dissolve result

   Parameter type: QgsProcessingParameterBoolean

   Accepted data types:
           - bool
           - int
           - str
           - QgsProperty

OUTPUT: Buffered

   Parameter type: QgsProcessingParameterFeatureSink

   Accepted data types:
           - str: destination vector file, e.g. 'd:/test.shp'
           - str: 'memory:' to store result in temporary memory layer
           - str: using vector provider ID prefix and destination URI,
                  e.g. 'postgres:...' to store result in PostGIS table
           - QgsProcessingOutputLayerDefinition
           - QgsProperty

----------------
Outputs
----------------

OUTPUT:  <QgsProcessingOutputVectorLayer>
   Buffered

Vous disposez maintenant de tout ce dont vous avez besoin pour exécuter n’importe quel algorithme. Comme nous l’avons déjà mentionné, les algorithmes peuvent être exécutés en utilisant:run(). Sa syntaxe est la suivante:

>>> processing.run(name_of_the_algorithm, parameters)

Où parameters est un dictionnaire de paramètres qui dépendent de l’algorithme que vous souhaitez exécuter, et est exactement la liste que la méthode algorithmHelp() vous donne.

1
2
3
4
5
6
7
8
 >>> processing.run("native:buffer", {'INPUT': '/data/lines.shp',
               'DISTANCE': 100.0,
               'SEGMENTS': 10,
               'DISSOLVE': True,
               'END_CAP_STYLE': 0,
               'JOIN_STYLE': 0,
               'MITER_LIMIT': 10,
               'OUTPUT': '/data/buffers.shp'})

Lorsqu’un paramètre est facultatif et que vous ne souhaitez pas l’utiliser, ne l’incluez pas dans le dictionnaire.

Lorsqu’un paramètre n’est pas indiqué, sa valeur par défaut est appliquée.

Selon le type de paramètre, les valeurs peuvent être fournies selon plusieurs manières. Une rapide description de ces possibilités est donnée pour chaque type de paramètre d’entrée :

  • Les couches raster, vecteur ou les tables. Indiquez simplement le nom identifiant la donnée (le nom dans la liste de couches de QGIS) ou un nom de fichier (si la couche n’a pas encore été ouverte, elle sera chargée mais pas ajoutée au canevas). Si vous avez une instance d’un objet QGIS représentant une couche, vous pouvez également la transmettre en paramètre.

  • Enumeration. Si un algorithme possède un paramètre d’énumération, la valeur de ce paramètre doit être saisie en utilisant une valeur entière. Pour connaître les options disponibles, vous pouvez utiliser la commande algorithmHelp(), comme ci-dessus. Par exemple, l’algorithme native:buffer a une énumération appelée JOIN_STYLE :

    JOIN_STYLE: Join style
    
       Parameter type: QgsProcessingParameterEnum
    
       Available values:
               - 0: Round
               - 1: Miter
               - 2: Bevel
    
       Accepted data types:
               - int
               - str: as string representation of int, e.g. '1'
               - QgsProperty
    

    Dans ce cas, le paramètre a trois options. Notez que la commande est basée sur zéro.

  • Booléen. Utilisez True ou False.

  • Entrées multiples. La valeur est une chaîne de caractères, avec les entrées séparées par des points-virgules (;). Comme pour les couches simples et les tables, chaque élément d’entrée peut être le nom d’une variable objet ou un nom de fichier.

  • Champ de la table XXX. Insérez une chaîne de caractères contenant le nom du champ à utiliser. Ce paramètre est sensible à la casse.

  • Table fixe. Entrez la liste de toutes les valeurs, séparées par des virgules (,) et entre guillemets ("). Les valeurs commencent par la première ligne et se lisent de gauche à droite. Vous pouvez aussi utiliser un tableau à deux dimensions pour représenter la table.

  • SCR. Entrez le code EPSG du système de coordonnées désiré.

  • Étendue. Vous devez fournir une chaîne de caractères avec les valeurs xmin, xmax, ymin et ymax séparées par des virgules (,).

Booléen, fichier, chaîne de caractères et valeurs numériques ne nécessitent pas d’explications particulières.

Les paramètres d’entrée tels que les chaînes, les booléens ou les valeurs numériques ont des valeurs par défaut. La valeur par défaut est utilisée si l’entrée de paramètre correspondante est manquante.

Pour les objets de données en sortie, saisissez le chemin d’accès au fichier à utiliser pour l’enregistrer, comme cela se fait à partir de la boîte à outils. Si l’objet de sortie n’est pas spécifié, le résultat est enregistré dans un fichier temporaire (ou ignoré s’il s’agit d’une sortie facultative). L’extension du fichier détermine le format du fichier. Si vous entrez une extension de fichier non prise en charge par l’algorithme, le format de fichier par défaut pour ce type de sortie sera utilisé et son extension correspondante ajoutée au chemin du fichier donné.

Contrairement à ce qui se passe lorsqu’un algorithme est exécuté depuis la boîte à outils, les résultats ne sont pas ajoutés au canevas de la carte si vous exécutez ce même algorithme depuis la console Python en utilisant run(), mais runAndLoadResults() le fera.

La méthode run() renvoie un dictionnaire avec un ou plusieurs noms de sortie (ceux indiqués dans la description de l’algorithme) comme clés et les chemins de fichier de ces sorties comme valeurs :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 >>> myresult = processing.run("native:buffer", {'INPUT': '/data/lines.shp',
               'DISTANCE': 100.0,
               'SEGMENTS': 10,
               'DISSOLVE': True,
               'END_CAP_STYLE': 0,
               'JOIN_STYLE': 0,
               'MITER_LIMIT': 10,
               'OUTPUT': '/data/buffers.shp'})
 >>> myresult['OUTPUT']
 /data/buffers.shp

Vous pouvez charger les résultats des entités en passant les chemins de fichiers correspondants à la méthode load(). Ou vous pouvez utiliser runAndLoadResults() au lieu de run() pour les charger immédiatement.

Si vous voulez ouvrir un dialogue d’algorithme depuis la console, vous pouvez utiliser la méthode « createAlgorithmDialog ». Le seul paramètre obligatoire est le nom de l’algorithme, mais vous pouvez également définir le dictionnaire des paramètres afin que le dialogue soit rempli automatiquement :

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
 >>> my_dialog = processing.createAlgorithmDialog("native:buffer", {
               'INPUT': '/data/lines.shp',
               'DISTANCE': 100.0,
               'SEGMENTS': 10,
               'DISSOLVE': True,
               'END_CAP_STYLE': 0,
               'JOIN_STYLE': 0,
               'MITER_LIMIT': 10,
               'OUTPUT': '/data/buffers.shp'})
 >>> my_dialog.show()

La méthode « ExecAlgorithmDialog » ouvre le dialogue immédiatement :

1
2
3
4
5
6
7
8
9
 >>> processing.execAlgorithmDialog("native:buffer", {
               'INPUT': '/data/lines.shp',
               'DISTANCE': 100.0,
               'SEGMENTS': 10,
               'DISSOLVE': True,
               'END_CAP_STYLE': 0,
               'JOIN_STYLE': 0,
               'MITER_LIMIT': 10,
               'OUTPUT': '/data/buffers.shp'})

23.7.2. Créer des scripts et les exécuter depuis la boîte à outils

Vous pouvez créer vos propres algorithmes en écrivant du code Python. Les scripts de traitement étendent QgsProcessingAlgorithm, vous devez donc ajouter des lignes de code supplémentaires pour implémenter les fonctions obligatoires. Vous pouvez trouver Créer un nouveau script (feuille blanche) et Créer un nouveau script à partir d’un modèle (modèle qui inclut le code pour les fonctions obligatoires de QgsProcessingAlgorithm) sous le menu déroulant Scripts en haut de la boîte à outils Traitement. L’éditeur de script de traitement s’ouvre et c’est là que vous devez taper votre code. L’enregistrement du script à partir de là dans le dossier scripts (le dossier par défaut lorsque vous ouvrez la boîte de dialogue d’enregistrement du fichier) avec une extension .py devrait créer l’algorithme correspondant.

Le nom de l’algorithme (celui que vous verrez dans la boîte à outils) est défini dans le code.

Jetons un coup d’œil au code suivant, qui définit un algorithme de traitement qui effectue une opération de tampon avec une distance de tampon définie par l’utilisateur sur une couche vecteur spécifiée par l’utilisateur, après avoir d’abord lissée la couche.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
from qgis.core import (QgsProcessingAlgorithm,
       QgsProcessingParameterNumber,
       QgsProcessingParameterFeatureSource,
       QgsProcessingParameterFeatureSink)

from qgis import processing

class algTest(QgsProcessingAlgorithm):
    INPUT_BUFFERDIST = 'BUFFERDIST'
    OUTPUT_BUFFER = 'OUTPUT_BUFFER'
    INPUT_VECTOR = 'INPUT_VECTOR'

    def __init__(self):
        super().__init__()

    def name(self):
        return "algTest"

    def displayName(self):
        return "algTest script"

    def createInstance(self):
        return type(self)()

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterFeatureSource(
            self.INPUT_VECTOR, "Input vector"))
        self.addParameter(QgsProcessingParameterNumber(
            self.INPUT_BUFFERDIST, "Buffer distance",
            QgsProcessingParameterNumber.Double,
            100.0))
        self.addParameter(QgsProcessingParameterFeatureSink(
            self.OUTPUT_BUFFER, "Output buffer"))

    def processAlgorithm(self, parameters, context, feedback):
        #DO SOMETHING
        algresult = processing.run("native:smoothgeometry",
            {'INPUT': parameters[self.INPUT_VECTOR],
             'ITERATIONS':2,
             'OFFSET':0.25,
             'MAX_ANGLE':180,
             'OUTPUT': 'memory:'},
            context=context, feedback=feedback, is_child_algorithm=True)
        smoothed = algresult['OUTPUT']
        algresult = processing.run('native:buffer',
            {'INPUT': smoothed,
            'DISTANCE': parameters[self.INPUT_BUFFERDIST],
            'SEGMENTS': 5,
            'END_CAP_STYLE': 0,
            'JOIN_STYLE': 0,
            'MITER_LIMIT': 10,
            'DISSOLVE': True,
            'OUTPUT': parameters[self.OUTPUT_BUFFER]},
            context=context, feedback=feedback, is_child_algorithm=True)
        buffered = algresult['OUTPUT']
        return {self.OUTPUT_BUFFER: buffered}

Après avoir effectué les importations nécessaires, les fonctions suivantes QgsProcessingAlgorithm sont spécifiées:

  • name() : L’id de l’algorithme (en minuscules).

  • displayName() : Un nom lisible par l’homme pour l’algorithme.

  • createInstance() : Pour créer une nouvelle instance de la classe d’algorithme.

  • initAlgorithm() : Configurer parameterDefinitions et outputDefinitions.

    Ici, vous décrivez les paramètres et la sortie de l’algorithme. Dans ce cas, une source d’entités pour l’entrée, un récepteur d’entités pour le résultat et un nombre pour la distance du tampon.

  • processAlgorithm() : Déclencher l’algorithme.

    Ici, nous exécutons d’abord l’algorithme smoothgeometry pour lisser la géométrie, puis nous exécutons l’algorithme buffer sur la sortie lissée. Pour pouvoir exécuter des algorithmes à partir d’un autre algorithme, nous devons définir le paramètre is_child_algorithm à True. Vous pouvez voir comment les paramètres d’entrée et de sortie sont utilisés comme paramètres pour les algorithmes de smoothgeometry et de buffer.

Plusieurs types de paramètres différents sont disponibles pour l’entrée et la sortie. Vous trouverez ci-dessous une liste triée par ordre alphabétique:

Le premier paramètre pour les constructeurs est le nom du paramètre et le second est la description du paramètre (pour l’interface utilisateur). Les autres paramètres du constructeur sont spécifiques au type de paramètre.

L’entrée peut être transformée en classes QGIS en utilisant les fonctions parameterAs de QgsProcessingAlgorithm. Par exemple, pour obtenir le nombre fourni pour la distance du tampon sous forme de double

self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).

La fonction processAlgorithm doit renvoyer un dictionnaire contenant des valeurs pour chaque sortie définie par l’algorithme. Cela permet d’accéder à ses sorties à partir d’autres algorithmes, y compris d’autres algorithmes contenus dans le même modèle.

Des algorithmes bien comportés devraient définir et renvoyer autant de sorties que cela a du sens. Les sorties sans entité, telles que les nombres et les chaînes, sont très utiles lors de l’exécution de votre algorithme dans le cadre d’un modèle plus large, car ces valeurs peuvent être utilisées comme paramètres d’entrée pour les algorithmes suivants au sein du modèle. Pensez à ajouter des sorties numériques pour des choses comme le nombre d’entités traitées, le nombre d’entités non valides rencontrées, le nombre de sorties d’entités, etc. Plus vous renvoyez de sorties, plus votre algorithme devient utile!

23.7.2.1. Retour d’informations

L’objet feedback() passé à processAlgorithm() doit être utilisé pour les commentaires / interactions des utilisateurs. Vous pouvez utiliser la fonction setProgress de l’objet feedback pour mettre à jour la barre de progression (0 à 100) pour informer l’utilisateur sur la progression de l’algorithme. Ceci est très utile si votre algorithme prend beaucoup de temps.

L’objet feedback() fournit une méthode isCanceled() qui doit être surveillée pour permettre l’annulation de l’algorithme par l’utilisateur. La méthode pushInfo() de feedback() peut être utilisée pour envoyer des informations à l’utilisateur et reportError() est pratique pour transmettre des erreurs non fatales aux utilisateurs.

Les algorithmes doivent éviter d’utiliser d’autres formes de rétroaction pour les utilisateurs, telles que des instructions d’impression ou la journalisation de QgsMessageLog, et doivent toujours utiliser à la place l’objet de rétroaction. Cela permet une journalisation détaillée de l’algorithme et est également compatible avec les threads (ce qui est important, étant donné que les algorithmes sont généralement exécutés dans un thread d’arrière-plan).

23.7.2.2. Gestion des erreurs

Si votre algorithme rencontre une erreur qui l’empêche de s’exécuter, telle que des valeurs d’entrée non valides ou une autre condition à partir de laquelle il ne peut pas ou ne doit pas récupérer, alors vous devez déclencher une QgsProcessingException. Par exemple.:

if feature['value'] < 20:
  raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))

Essayez d’éviter de déclencher QgsProcessingException pour les erreurs non fatales (par exemple lorsqu’une entité a une géométrie nulle), et au lieu de cela, signalez simplement ces erreurs via feedback.reportError() et ignorez l’entité. Cela permet de rendre votre algorithme «convivial pour le modèle», car il évite d’arrêter l’exécution d’un algorithme entier lorsqu’une erreur non fatale est rencontrée.

23.7.2.3. Documenter ses scripts

Comme dans le cas des modèles, vous pouvez créer une documentation supplémentaire pour vos scripts, pour expliquer ce qu’ils font et comment les utiliser.

La classe QgsProcessingAlgorithm() fournit les métodes helpString(), shortHelpString() et helpUrl() à cet effet. Spécifiez / remplacez-les pour fournir plus d’aide à l’utilisateur.

shortDescription() est utilisé dans l’info-bulle lors du survol de l’algorithme dans la boîte à outils.

23.7.3. Scripts de pré et post-exécution

Les scripts peuvent également être utilisés comme accrochage avant et après l’exécution et seront exécutés, respectivement, avant et après l’exécution d’un algorithme. Cela peut être utilisé pour automatiser les tâches qui doivent être effectuées chaque fois qu’un algorithme est exécuté.

La syntaxe est identique à celle qui est expliquée plus haut mais une variable globale nommée alg est disponible. Elle représente l’objet algorithme qui vient (ou qui va) être lancé.

Dans le groupe Général de la boîte de dialogue des options de traitement, vous trouverez deux entrées nommées Script de pré-exécution et Script de post-exécution où les noms de fichiers des scripts à exécuter chaque cas peut être saisi.