Написання сценарію обробки пітона за допомогою QGIS 3.0


17

Після оновлення до QGIS 3.0 стало важко знайти будь-яку інформацію, що стосується написання сценаріїв обробки в QGIS 3.0.

@Underdark (див. Тут ) створив основу для скелета. Цей код також, здається, був доданий у QGIS під час написання нового сценарію із шаблону (QGIS 3.0.2).

Однак я не зміг знайти жодного способу допомогти новачкам Python, як я, зрозуміти, як змінити цей код, особливо для вхідних та вихідних шарів.

Моя мета - написати сценарій, який буде вводити 2 растрових шари та подвійний як вихідний, виводячи два шари.

Якими будуть зміни, необхідні для прикладу коду, щоб дозволити це?

Для QGIS 2.x я використав би такий синтаксис:

##Layer1=raster
##Layer2=raster 
##myDouble=Double
##OutLayer1=output raster
##OutLayer2=output raster   

З того, що я розумію, зміни повинні бути внесені в наступній процедурі, але я не впевнений, що робити.

def initAlgorithm(self, config=None):
    self.addParameter(QgsProcessingParameterFeatureSource(
        self.INPUT,
        self.tr("Input layer"),
        [QgsProcessing.TypeVectorAnyGeometry]))
    self.addParameter(QgsProcessingParameterFeatureSink(
        self.OUTPUT,
        self.tr("Output layer"),
        QgsProcessing.TypeVectorAnyGeometry))

16 травня було випущено документацію QGIS Python API . Однак мені досі незрозуміло, як тут користуватися. (Що може бути недостатньо знань Python)


1
Чи можете ви надати зразок коду, який ви використовували з тією ж метою, на qgis 2.xx Документація на qgis 3.x буде доступна тут: docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/…, як тільки це буде оновлено. Проблеми з документами відстежуються тут: github.com/qgis/QGIS-Documentation/issues
Nono

Відповідь відредаговано на прикладі коду. Дякую за посилання, я вже слідкував за кулінарною книгою, але, на жаль, не зміг знайти там свою відповідь!
Кантань

Я читав про документи Qgis API, але не можу пов'язати це з кодом @Underdark. (див. редагування для посилань)
Кантань

Відповіді:


29

З переходом від QGIS2.x до QGIS3.x весь фреймворк обробки був перероблений, і велика частина його працює зараз як C ++ класи, з якими можна взаємодіяти за допомогою Python. На жаль, простий синтаксис параметрів для IO даних / набору даних більше не дійсний. Нова структура параметрів набагато більш орієнтована після вбудованих (Python-) алгоритмів обробки, які ви знайдете заздалегідь встановленими в панелі інструментів.

Як я бачу, ви вже стежили за описом нової структури алгоритму від @underdark. Але для того, щоб налаштувати цю структуру під свої вимоги (растрові шари, подвійне введення тощо), вам потрібно змінити код у кількох місцях сценарію. Я зашифрував приблизний приклад з коротким поясненням для вас (просто скелет алгоритму на основі прикладу @underdarks):

from qgis.PyQt.QtCore import QCoreApplication, QVariant
from qgis.core import (QgsProcessing, QgsProcessingAlgorithm, 
QgsProcessingParameterRasterLayer,QgsProcessingParameterNumber, 
QgsProcessingParameterRasterDestination)

class RasterAlg(QgsProcessingAlgorithm):
    INPUT_RASTER_A = 'INPUT_RASTER_A'
    INPUT_RASTER_B = 'INPUT_RASTER_B'
    INPUT_DOUBLE = 'INPUT_DOUBLE'
    OUTPUT_RASTER_A = 'OUTPUT_RASTER_A'
    OUTPUT_RASTER_B = 'OUTPUT_RASTER_B'

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

    def name(self):
        return "RasterAlg"

    def tr(self, text):
        return QCoreApplication.translate("RasterAlg", text)

    def displayName(self):
        return self.tr("RasterAlg script")

    def group(self):
        return self.tr("RasterAlgs")

    def groupId(self):
        return "RasterAlgs"

    def shortHelpString(self):
        return self.tr("RasterAlg script without logic")

    def helpUrl(self):
        return "https://qgis.org"

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

    def initAlgorithm(self, config=None):
        self.addParameter(QgsProcessingParameterRasterLayer(
            self.INPUT_RASTER_A,
            self.tr("Input Raster A"), None, False))
        self.addParameter(QgsProcessingParameterRasterLayer(
            self.INPUT_RASTER_B,
            self.tr("Input Raster B"), None, False))
        self.addParameter(QgsProcessingParameterNumber(
            self.INPUT_DOUBLE, 
            self.tr("Input Double"), 
            QgsProcessingParameterNumber.Double,
            QVariant(1.0)))
        self.addParameter(QgsProcessingParameterRasterDestination(
            self.OUTPUT_RASTER_A,
            self.tr("Output Raster A"),
            None, False))
        self.addParameter(QgsProcessingParameterRasterDestination(
            self.OUTPUT_RASTER_B,
            self.tr("Output Raster B"),
            None, False))

    def processAlgorithm(self, parameters, context, feedback):
        raster_a = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER_A, context)
        raster_b = self.parameterAsRasterLayer(parameters, self.INPUT_RASTER_B, context)
        double_val = self.parameterAsDouble(parameters, self.INPUT_DOUBLE,context)
        output_path_raster_a = self.parameterAsOutputLayer(parameters, self.OUTPUT_RASTER_A, context)
        output_path_raster_b = self.parameterAsOutputLayer(parameters, self.OUTPUT_RASTER_B, context)

        #DO SOME CALCULATION

        results = {}
        results[self.OUTPUT_RASTER_A] = output_path_raster_a
        results[self.OUTPUT_RASTER_B] = output_path_raster_b
        return results

Які кроки зроблено?

  1. Імпортуйте всі необхідні класи.
  2. Визначте алгоритм як клас, успадкований від QgsProcessingAlgorithm.
  3. Спочатку вам слід оголосити назви вхідних та вихідних параметрів як рядкові змінні (назви параметрів) класу алгоритму (тобто INPUT_RASTER_A = 'INPUT_RASTER_A'), щоб посилатись на ваш алгоритм з параметрами, наданими рамкою обробки.
  4. Додайте методи, що передають ваш алгоритм, до gui інструментів для обробки даних та надають довідки тощо.
  5. Потім ви додаєте параметри рамки обробки. Вони визначаються як дочірні класи QgsProcessingParameterType- в разі вашого алгоритму: QgsProcessingParameterRasterLayer, QgsProcessingParameterNumberі так далі. Ви можете проконсультувати записи API (тобто QgsProcessingParameterRasterLayer) для передачі правильних аргументів та побудови об'єктів параметрів.
  6. Передайте параметри поряд contextі feedbackоб'єкти processAlgorithm()методу, де ви отримуєте набори вхідних наборів даних з параметрів під час виконання (у цьому випадку об'єкти QgsRasterLayer, використовуючи parameterAsRasterLayer()метод тощо).
  7. Зробіть свої обчислення.
  8. Додайте вихідні дані до словника результатів та поверніть їх у результаті виклику processAlgorithm().

Я сподіваюся, що я міг би дати вам деяку інформацію про те, як розробити алгоритми python у QGIS3. Щоразу, коли ви застрягли, завжди корисно подивитися, як існуючі алгоритми рамки обробки обробляють параметри. Ви можете подивитися на них тут .


1
Гарна реєстрація! Майте на увазі, якщо я додам його до github.com/qgis/QGIS/blob/master/doc/porting_processing.dox ?
ndawson

Мені буде честь, якщо ви додасте його до документації qgis. Будь ласка, зробіть це! Чи є якісь передумови для надання додаткової документації python для qgis3? Я думаю, що це важливо для більш широкої бази користувачів з точки зору сценаристів та програмістів.
root676

1
Передумов немає. Додавати до офіційної кухонної книги python насправді досить просто через запити на витяг GitHub (всі зміни можна навіть зробити на сайті GitHub: github.com/qgis/QGIS-Documentation/tree/master/source/docs/… ). Додавання додаткових прикладів до офіційних документів також буде дуже вітається!
ndawson

1
Дякую за вашу відповідь! Я сьогодні був зайнятий, але завтра спробую копатись. Це виглядає дійсно перспективно.
Кантань

2
Це, безумовно, чудова відповідь, дякую за деталі та посилання. Посилання на скрипти на gitHub - справжня золота мина! Спочатку декларація QVariant дала мені помилку, але коли я повторно ввів її в редактор і застосував автоматичне завершення, помилка зникла. Зараз дійсно робиться великий крок, щоб зануритися в сценарій, я сподіваюся, що це не відлякує нових програмістів. Оскільки доступно більше документації, я сподіваюся, що це стане зрозумілішим!
Кантань
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.