Viết kịch bản xử lý python với Qgis 3.0


14

Sau khi cập nhật lên Qgis 3.0, việc tìm kiếm bất kỳ thông tin nào liên quan đến việc viết các tập lệnh xử lý trong Qgis 3.0 trở nên rất khó khăn.

@Underdark (xem tại đây ) đã cung cấp một cơ sở cho bộ xương. Mã này dường như cũng đã được thêm vào trong Qgis, khi viết một tập lệnh mới từ mẫu (Qgis 3.0.2).

Tuy nhiên, tôi không thể tìm thấy bất kỳ cách nào để giúp những người mới chơi python như tôi hiểu cách thay đổi mã đó, đặc biệt là cho các lớp đầu vào và đầu ra.

Mục tiêu của tôi là viết một kịch bản lấy 2 lớp raster và gấp đôi làm đầu vào, xuất ra hai lớp.

Điều gì sẽ là những thay đổi cần thiết cho mã ví dụ để cho phép điều đó?

Đối với Qgis 2.x tôi đã sử dụng cú pháp sau:

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

Theo những gì tôi hiểu, các thay đổi phải được thực hiện theo quy trình sau, nhưng tôi không chắc nên đặt gì vào vị trí.

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

Vào ngày 16 tháng 5, tài liệu API python Qgis đã được phát hành. Tuy nhiên vẫn chưa rõ ràng cho tôi làm thế nào để sử dụng nó ở đây. (Điều này rất có thể là thiếu kiến ​​thức về trăn)


1
Bạn có thể cung cấp một mẫu mã bạn đã sử dụng cho cùng mục đích trên qgis 2.xx Tài liệu về qgis 3.x sẽ có sẵn ở đây: docs.qgis.org/testing/en/docs/pyqgis_developer_cookbook/, ngay khi nó sẽ cập nhật. Các vấn đề về tài liệu được theo dõi tại đây: github.com/qgis/QGIS-Documentation/issues
Nono

Trả lời chỉnh sửa với ví dụ mã. Cảm ơn các liên kết, tôi đã theo dõi sách dạy nấu ăn nhưng tiếc là tôi không thể tìm thấy câu trả lời của mình ở đó!
Kantan

Tôi đã đọc về các tài liệu API của Qgis, nhưng tôi không thể liên quan giữa mã đó và mã của @Underdark. (xem chỉnh sửa cho các liên kết)
Kantan

Câu trả lời:


26

Với việc chuyển đổi từ QGIS2.x sang QGIS3.x, toàn bộ khung xử lý đã được làm lại và phần lớn của nó chạy như các lớp C ++ mà bạn có thể tương tác bằng Python. Thật không may, cú pháp tham số đơn giản cho dữ liệu / dữ liệu IO không còn hợp lệ. Cấu trúc tham số mới được định hướng nhiều hơn sau các thuật toán xử lý dựng sẵn (Python-) mà bạn tìm thấy được cài đặt sẵn trong hộp công cụ.

Như tôi thấy, bạn đã làm theo mô tả về cấu trúc thuật toán mới của @underdark. Nhưng để điều chỉnh cấu trúc này cho các yêu cầu của bạn (các lớp raster, đầu vào kép, v.v.), bạn phải thay đổi mã tại nhiều vị trí trong tập lệnh. Tôi đã mã hóa một ví dụ sơ bộ với một lời giải thích ngắn cho bạn (chỉ là một bộ xương thuật toán dựa trên ví dụ @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

Những bước nào được thực hiện?

  1. Nhập tất cả các lớp cần thiết.
  2. Xác định thuật toán là một lớp kế thừa từ QgsProcessingAlgorithm.
  3. Trước tiên, bạn phải khai báo tên của các tham số đầu vào và đầu ra dưới dạng các biến chuỗi (tên tham số) của lớp thuật toán (ví dụ. INPUT_RASTER_A = 'INPUT_RASTER_A') Để tham chiếu thuật toán của bạn với các tham số được cung cấp bởi khung xử lý.
  4. Thêm các phương thức kết nối thuật toán của bạn với gui của hộp công cụ xử lý và cung cấp trợ giúp, v.v.
  5. Sau đó, bạn thêm các tham số của khung xử lý. Chúng được định nghĩa là các lớp con của QgsProcessingParameterType- trong trường hợp thuật toán của bạn : QgsProcessingParameterRasterLayer, QgsProcessingParameterNumberv.v. Bạn có thể tham khảo các mục API (ví dụ. QgsProcessingParameterRasterLayer) Để truyền đúng đối số và xây dựng các đối tượng tham số.
  6. Vượt qua các thông số bên cạnh contextfeedbackđối tượng để các processAlgorithm()phương pháp mà bạn có được bộ dữ liệu đầu vào từ các thông số khi chạy (trong trường hợp này QgsRasterLayer đối tượng bằng cách sử dụng các parameterAsRasterLayer()phương pháp, vv).
  7. Làm tính toán của bạn.
  8. Thêm các kết quả đầu ra vào từ điển kết quả và trả về chúng như là kết quả của cuộc gọi processAlgorithm().

Tôi hy vọng tôi có thể cung cấp cho bạn một số hiểu biết về cách thiết kế các thuật toán python của bạn trong QGIS3. Bất cứ khi nào bạn bị mắc kẹt, luôn luôn hữu ích để xem xét các thuật toán hiện có của khung xử lý xử lý các tham số. Bạn có thể có một cái nhìn tại đây .


1
Tốt viết! Có phiền nếu tôi thêm nó vào github.com/qgis/QGIS/blob/master/doc/porting_ Processing.dox ?
ndawson

Tôi sẽ rất vinh dự nếu bạn thêm nó vào tài liệu của qgis. Xin hãy làm như vậy! Có bất kỳ điều kiện tiên quyết để đóng góp thêm tài liệu python cho qgis3? Tôi nghĩ rằng điều này là cần thiết cho một cơ sở người dùng rộng hơn về mặt các nhà viết kịch bản và lập trình viên.
root676

1
Không có điều kiện tiên quyết. Thật sự khá dễ dàng để thêm vào sách dạy nấu ăn trăn chính thức thông qua các yêu cầu kéo GitHub (tất cả các chỉnh sửa thậm chí có thể được thực hiện trên trang GitHub: github.com/qgis/QGIS-Documentation/tree/master/source/docs/ocate ). Thêm nhiều ví dụ cho các tài liệu chính thức cũng sẽ rất được hoan nghênh!
ndawson

1
Cảm ơn câu trả lời của bạn! Hôm nay tôi bận, nhưng tôi sẽ cố gắng đào vào ngày mai. Nó trông thực sự hứa hẹn.
Kantan

2
Đó chắc chắn là một câu trả lời tuyệt vời, cảm ơn các chi tiết và tài liệu tham khảo. Liên kết đến các tập lệnh trên gitHub là một goldmine thực sự! Lúc đầu, khai báo QVariant đã cho tôi một lỗi, nhưng khi tôi gõ lại nó trong trình chỉnh sửa và sử dụng hoàn thành tự động, lỗi đã biến mất. Bây giờ nó thực sự là một bước tiến lớn để đi sâu vào kịch bản, tôi hy vọng nó không làm nản lòng các lập trình viên mới. Mặc dù có nhiều tài liệu hơn, tôi hy vọng nó sẽ trở nên rõ ràng hơn!
Kantan
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.