Simplifiez les tâches répétitives dans QGIS Graphical Modeler

13

entrez la description de l'image ici

Y a-t-il des itérateurs qui peuvent être utilisés dans le modeleur graphique QGIS pour simplifier le modèle montré ci-dessus. Sinon, existe-t-il une meilleure façon de simplifier le modèle?

La première colonne représente mes couches d'entrée, la deuxième colonne est l'intersection, la troisième colonne est la sortie de l'opération "intersection", la quatrième colonne est l'opération "join attribute by location" et la cinquième colonne est le résultat de l'opération join.

Je souhaite réaliser des opérations «intersection» et «joindre attribut par emplacement» pour une analyse de bassin versant. L'objectif est de calculer des paramètres morphométriques linéaires tels que la longueur totale et moyenne des flux de différents ordres, les ratios de flux et le rapport de bifurcation.

La première étape consiste à croiser les «ruisseaux Order1» avec le bassin versant, puis à croiser les «ruisseaux Order2» avec le même bassin versant. Si un fichier de formes "stream3 order3" est fourni, l'intersection de cette nouvelle couche doit être effectuée. Par conséquent, seuls les "ruisseaux order1" et "streams order2" sont obligatoires, le reste dépend de la couche de bassin versant fournie. Par exemple, si le bassin versant est un bassin versant d'ordre 4, les cours d'eau requis sont jusqu'à «cours d'eau d'ordre 4».

Une fois l'intersection terminée pour toutes les couches d'entrée disponibles, elles sont ensuite jointes par emplacement au bassin versant avec les options pour obtenir la somme et la moyenne des cours d'eau intersectés.

L'image montre la procédure correcte. Si je fais l'opération en dehors du modeleur, les résultats sont corrects. Lorsque j'exécute le modèle, j'obtiens cette erreur.

"Erreur lors de l'exécution de l'algorithme Order5_plus_wshed, l'objet 'NoneType' n'a pas d'attribut 'dataProvider'".

Cela se produit si je n'ai pas fourni d'entrée pour l'un des paramètres facultatifs (c'est-à-dire les entrées, par exemple "flux order4"). Cependant, si je fournis toutes les entrées, j'obtiens les résultats dont j'ai besoin.

Je voudrais donc demander s'il existe une meilleure façon de mettre en place cette tâche.

DennisTG
la source

Réponses:

12

La façon dont je définirais votre tâche serait de créer un script personnalisé qui offre une plus grande flexibilité que le modélisateur mais peut toujours fournir une interface similaire à ses utilisateurs. Vous pouvez en créer un à partir de:

Boîte à outils de traitement> Scripts> Outils> Créer un nouveau script

Copiez / collez ensuite le script ci-dessous et enregistrez-le dans C:/Users/You/.qgis2/processing/scripts.

Le script ci-dessous essaie d'émuler ce que fait votre modèle. Le script n'est pas une solution finale (d'autant plus que les paramètres que j'ai utilisés pour l' attribut Intersection et jointure par les outils de localisation peuvent différer de ce que vous avez défini) mais j'espère que vous pourrez l'utiliser comme modèle pour développer et améliorer le script en fonction de vos besoins . Pour l'exécuter, il suffit de le sélectionner dans la boîte à outils de traitement après l'avoir enregistré.

Je pense que le script fait ce que vous avez demandé:

  • Les deux premières commandes sont obligatoires et seront donc traitées.

  • IF Les instructions sont utilisées pour garantir que toute commande suivante ne sera traitée que si la bonne la précède (par exemple order4 ne s'exécutera que si order3 a été sélectionnée).

  • De plus, des messages sont imprimés dans la console Python indiquant les commandes en cours de traitement.


##Example model=name
##Order1=vector
##Order2=vector
##Order3=optional vector
##Order4=optional vector
##Order5=optional vector
##Watershed=vector
##Order2_Wshed=output vector
##Order3_Wshed=output vector
##Order4_Wshed=output vector
##Order5_Wshed=output vector

order1 = processing.getObject(Order1)
order2 = processing.getObject(Order2)
order3 = processing.getObject(Order3)
order4 = processing.getObject(Order4)
order5 = processing.getObject(Order5)
watershed = processing.getObject(Watershed)

if Order3 is None:
    print 'Processing Order1 and Order2'
else:
    print 'Processing Order1, Order2 and Order3'
    if Order4 is not None:
        print 'Processing Order1, Order2, Order3 and Order4'
        if Order5 is not None:
            print 'Processing Order1, Order2, Order3, Order4 and Order5'

output_1a = processing.runalg("qgis:intersection", order1, watershed, None)
output_1b = processing.runalg("qgis:joinattributesbylocation", output_1a['OUTPUT'], watershed, u'intersects', 0, 0, '', 0, None)
output_2a = processing.runalg("qgis:intersection", order2, watershed, None)
output_2b = processing.runalg("qgis:joinattributesbylocation", output_2a['OUTPUT'], output_1b['OUTPUT'], u'intersects', 0, 0, '', 0, Order2_Wshed)

if Order3 is None:
    pass
else:
    output_3a = processing.runalg("qgis:intersection", order3, watershed, None)
    output_3b = processing.runalg("qgis:joinattributesbylocation", output_3a['OUTPUT'], output_2b['OUTPUT'], u'intersects', 0, 0, '', 0, Order3_Wshed)
    if Order4 is None:
        pass
    else:
        output_4a = processing.runalg("qgis:intersection", order4, watershed, None)
        output_4b = processing.runalg("qgis:joinattributesbylocation", output_4a['OUTPUT'], output_3b['OUTPUT'], u'intersects', 0, 0, '', 0, Order4_Wshed)
        if Order5 is None:
            pass
        else:
            output_5a = processing.runalg("qgis:intersection", order5, watershed, None)
            output_5b = processing.runalg("qgis:joinattributesbylocation", output_5a['OUTPUT'], output_4b['OUTPUT'], u'intersects', 0, 1, 'sum, mean', 0, Order5_Wshed)

Voici une capture d'écran de l'interface lors de l'exécution du script (qui devrait ressembler à celle de votre modèle):

Script en cours d'exécution

Peu de choses à noter:

  • La boîte rouge contient les paramètres obligatoires

  • La boîte verte contient des paramètres facultatifs

  • La boîte bleue contient un paramètre obligatoire

  • La boîte noire contient des paramètres facultatifs pour produire les résultats. Le script ne sortira les couches que si l'ordre associé est sélectionné (par exemple, si l'entrée pour order5 n'est pas sélectionnée mais la sortie correspondant, une erreur se produira). Par conséquent, l'utilisateur doit sélectionner les entrées et les sorties pertinentes. Ce n'était pas intentionnel mais personnellement, je pense que c'est un bon moyen de forcer l'utilisateur à vérifier soigneusement les paramètres.


J'ai utilisé QGIS 2.12.3 (avec le plugin Processing version 2.12.2).

Joseph
la source
2
Lors d'un récent podcast QGIS, le créateur du traitement était activé, et il a déclaré qu'en raison de la façon dont il était construit, vous ne pouviez pas ajouter d'itérateur directement dans le générateur de modèles maintenant. Il faudrait une réécriture approfondie pour l'ajouter. Un script personnalisé est donc définitivement le moyen de le faire pour l'instant.
HeikkiVesanto
@Vesanto - C'est très intéressant, merci de l'inclure. Avez-vous un lien vers ce podcast particulier?
Joseph
1
@DennisTG - Copain d'excuses, j'aurais dû mentionner dans mon article que j'ai utilisé QGIS 2.12.3 (avec le plugin Processing version 2.12.2).
Joseph
1
@Joseph, cela fonctionne pour moi. Très perspicace, j'apprécie l'aide.
DennisTG