Menulis skrip pemrosesan python dengan Qgis 3.0

15

Setelah pembaruan ke Qgis 3.0, menjadi sangat sulit untuk menemukan informasi mengenai penulisan skrip pemrosesan di Qgis 3.0.

@Underdark (lihat di sini ) telah memberikan dasar untuk kerangka. Kode ini juga tampaknya telah ditambahkan dalam Qgis, saat menulis skrip baru dari templat (Qgis 3.0.2).

Namun, saya tidak dapat menemukan cara untuk membantu pemula python seperti saya untuk memahami cara mengubah kode itu, terutama untuk lapisan input dan output.

Tujuan saya adalah menulis skrip yang mengambil 2 layer raster dan double sebagai input, menghasilkan dua layer.

Apa perubahan yang diperlukan pada kode contoh untuk memperbolehkannya?

Untuk Qgis 2.x saya akan menggunakan sintaks berikut:

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

Dari apa yang saya mengerti, perubahan harus dilakukan dalam prosedur berikut, tetapi saya tidak yakin apa yang harus dilakukan.

    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))

Pada 16 Mei, dokumentasi API python Qgis dirilis. Namun masih belum jelas bagi saya bagaimana menggunakannya di sini. (Yang mungkin sangat kurangnya pengetahuan python)

Kantan
sumber
1
Bisakah Anda memberikan contoh kode yang Anda gunakan untuk tujuan yang sama pada qgis 2.xx Dokumentasi pada qgis 3.x akan tersedia di sini: docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/… segera setelah itu akan diperbarui. Masalah dokumen
Nono
Jawaban diedit dengan contoh kode. Terima kasih atas tautannya, saya sudah mengikuti buku masak tapi sayangnya saya tidak dapat menemukan jawaban saya di sana!
Kantan
Saya membaca tentang dokumentasi API Qgis, tetapi saya tidak dapat menghubungkan antara itu dan kode @Underdark. (lihat edit untuk
tautannya

Jawaban:

26

Dengan transisi dari QGIS2.x ke QGIS3.x seluruh kerangka kerja pemrosesan telah dikerjakan ulang dan sebagian besar dijalankan sekarang sebagai kelas C ++ yang dapat Anda berinteraksi dengan menggunakan Python. Sayangnya sintaks parameter sederhana untuk data / dataset IO tidak lagi valid. Struktur parameter baru jauh lebih berorientasi setelah algoritma Pemrosesan bawaan (Python-) yang Anda temukan sudah diinstal sebelumnya di kotak peralatan.

Seperti yang saya lihat, Anda sudah mengikuti deskripsi struktur algoritma baru oleh @underdark. Tetapi untuk menyesuaikan struktur ini untuk kebutuhan Anda (layer raster, input ganda, dll.) Anda harus mengubah kode di beberapa lokasi dalam skrip. Saya telah memberi kode contoh kasar dengan penjelasan singkat untuk Anda (hanya kerangka algoritma berdasarkan contoh @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

Langkah mana yang dilakukan?

  1. Impor semua kelas yang diperlukan.
  2. Tetapkan algoritma sebagai kelas yang diwarisi dari QgsProcessingAlgorithm.
  3. Pertama, Anda harus mendeklarasikan nama parameter input dan output sebagai variabel string (nama parameter) dari kelas algoritma (mis. INPUT_RASTER_A = 'INPUT_RASTER_A') Untuk referensi algoritma Anda dengan parameter yang disediakan oleh kerangka kerja pemrosesan.
  4. Tambahkan metode yang menyambungkan algoritma Anda ke gui toolbox pemrosesan dan berikan bantuan, dll.
  5. Kemudian Anda menambahkan parameter kerangka kerja pemrosesan. Mereka didefinisikan sebagai kelas anak QgsProcessingParameterType- dalam kasus algoritma Anda: QgsProcessingParameterRasterLayer, QgsProcessingParameterNumber, dan sebagainya. Anda dapat berkonsultasi entri API (mis. QgsProcessingParameterRasterLayer) Untuk memberikan argumen yang benar dan membangun objek parameter.
  6. Lewati parameter di samping contextdan feedbackobjek ke processAlgorithm()metode di mana Anda mendapatkan dataset input dari parameter saat runtime (dalam hal ini objek QgsRasterLayer dengan menggunakan parameterAsRasterLayer()metode, dll.).
  7. Lakukan perhitungan Anda.
  8. Tambahkan output ke kamus hasil dan kembalikan sebagai hasil panggilan processAlgorithm().

Saya harap saya bisa memberi Anda beberapa wawasan tentang bagaimana merancang algoritma python Anda di QGIS3. Setiap kali Anda macet, selalu membantu untuk melihat bagaimana algoritma yang ada dari kerangka kerja menangani parameter. Anda dapat melihatnya di sini .

root676
sumber
1
Langgan yang bagus! Keberatan jika saya menambahkannya ke github.com/qgis/QGIS/blob/master/doc/porting_processing.dox ?
ndawson
Saya akan merasa terhormat jika Anda menambahkannya ke dokumentasi qgis. Tolong lakukan itu! Apakah ada prasyarat untuk berkontribusi lebih banyak dokumentasi python untuk qgis3? Saya pikir ini penting untuk basis pengguna yang lebih luas dalam hal skrip dan programmer.
root676
1
Tidak ada prasyarat. Sebenarnya cukup mudah untuk menambah buku resep python resmi melalui permintaan tarik GitHub (semua pengeditan bahkan dapat dilakukan di situs GitHub: github.com/qgis/QGIS-Documentation/tree/master/source/docs/… ). Menambahkan lebih banyak contoh ke dokumen resmi juga akan sangat disambut baik!
ndawson
1
Terima kasih atas jawaban anda! Saya sibuk hari ini, tetapi saya akan mencoba menggali besok. Terlihat sangat menjanjikan.
Kantan
2
Itu pasti jawaban yang bagus, terima kasih untuk detail dan referensi. Tautan ke skrip di gitHub adalah tambang emas asli! Pada awalnya deklarasi QVariant memberi saya kesalahan, tetapi ketika saya mengetik ulang di editor dan menggunakan penyelesaian otomatis, kesalahan itu hilang. Sekarang benar-benar mengambil langkah besar untuk menyelam dalam skrip, saya harap itu tidak membuat programer baru. Karena lebih banyak dokumentasi tersedia, saya harap ini menjadi lebih jelas!
Kantan