การเขียนสคริปต์ประมวลผลหลามด้วย 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/ทันทีที่มันเป็น อัปเดต มีการติดตามปัญหาของ Doc ที่นี่: github.com/qgis/QGIS-Documentation/issues
Nono

คำตอบแก้ไขด้วยตัวอย่างรหัส ขอบคุณสำหรับลิงค์ฉันทำตามตำราแล้ว แต่น่าเสียดายที่ฉันไม่พบคำตอบที่นั่น!
Kantan

ฉันอ่านเกี่ยวกับเอกสาร Qgis API แต่ฉันไม่สามารถเชื่อมโยงระหว่างสิ่งนั้นกับรหัสของ @Underdark (ดูการแก้ไขสำหรับลิงก์)
Kantan

คำตอบ:


29

ด้วยการเปลี่ยนจาก QGIS2.x เป็น QGIS3.x เฟรมเวิร์กการประมวลผลทั้งหมดได้รับการทำใหม่และส่วนใหญ่ของมันจะทำงานในขณะนี้เป็นคลาส C ++ ที่คุณสามารถโต้ตอบกับการใช้ Python น่าเสียดายที่ไวยากรณ์พารามิเตอร์อย่างง่ายสำหรับ data / dataset 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. เพิ่มวิธีการที่เชื่อมโยงอัลกอริทึมของคุณไปยังกล่องเครื่องมือประมวลผลและให้ความช่วยเหลือ ฯลฯ
  5. จากนั้นคุณเพิ่มพารามิเตอร์ของเฟรมเวิร์กการประมวลผล เหล่านั้นจะถูกกำหนดให้เป็นชั้นเรียนเด็กQgsProcessingParameterType- ในกรณีของอัลกอริทึมของคุณ: QgsProcessingParameterRasterLayer, QgsProcessingParameterNumberและอื่น ๆ คุณสามารถศึกษารายการ API (เช่น. QgsProcessingParameterRasterLayer) เพื่อส่งผ่านอาร์กิวเมนต์ที่ถูกต้องและสร้างวัตถุพารามิเตอร์
  6. ส่งพารามิเตอร์ข้างcontextและfeedbackวัตถุไปยังprocessAlgorithm()วิธีการที่คุณได้รับชุดข้อมูลอินพุตจากพารามิเตอร์ที่ runtime (ในกรณีนี้วัตถุ QgsRasterLayer โดยใช้parameterAsRasterLayer()วิธีการ ฯลฯ )
  7. ทำการคำนวณของคุณ
  8. processAlgorithm()เพิ่มผลผลิตผลการพจนานุกรมและพวกเขากลับเป็นผลของการโทร

ฉันหวังว่าฉันจะให้ข้อมูลเชิงลึกเกี่ยวกับวิธีออกแบบ python algorithm ของคุณใน QGIS3 เมื่อใดก็ตามที่คุณติดอยู่จะเป็นประโยชน์เสมอที่จะดูว่าอัลกอริทึมที่มีอยู่ของเฟรมเวิร์กการประมวลผลจัดการกับพารามิเตอร์อย่างไร คุณสามารถดูได้ที่พวกเขาที่นี่


1
เขียนได้ดีมาก! ถ้าผมเพิ่มเข้าไปgithub.com/qgis/QGIS/blob/master/doc/porting_processing.dox ?
ndawson

ฉันจะได้รับเกียรติถ้าคุณเพิ่มลงในเอกสาร qgis กรุณาทำ! มีข้อกำหนดเบื้องต้นใดบ้างสำหรับการมีส่วนร่วมในเอกสาร python เพิ่มเติมสำหรับ qgis3 ฉันคิดว่านี่เป็นสิ่งจำเป็นสำหรับฐานผู้ใช้ที่กว้างขึ้นในแง่ของสแครปเตอร์และโปรแกรมเมอร์
root676

1
ไม่มีข้อกำหนดเบื้องต้น จริง ๆ แล้วมันค่อนข้างง่ายที่จะเพิ่มไปยังตำราอาหารไพ ธ อนอย่างเป็นทางการผ่านคำขอดึง GitHub (การแก้ไขทั้งหมดสามารถทำได้บนเว็บไซต์ GitHub: github.com/qgis/QGIS/QGIS-Documentation/tree/master/source/docs/ … ) การเพิ่มตัวอย่างเพิ่มเติมให้กับเอกสารอย่างเป็นทางการก็ยินดีด้วยเช่นกัน!
ndawson

1
ขอบคุณสำหรับคำตอบ! ฉันยุ่งในวันนี้ แต่ฉันจะพยายามขุดในวันพรุ่งนี้ มันดูมีแนวโน้มจริงๆ
Kantan

2
นั่นเป็นคำตอบที่ดีขอบคุณสำหรับรายละเอียดและการอ้างอิง ลิงค์ไปยังสคริปต์ของ gitHub นั้นเป็นทองคำแท้! ตอนแรกการประกาศ QVariant ทำให้ฉันมีข้อผิดพลาด แต่เมื่อฉันพิมพ์ซ้ำในตัวแก้ไขและใช้การทำให้สมบูรณ์อัตโนมัติข้อผิดพลาดก็หายไป ตอนนี้เป็นขั้นตอนใหญ่ในการดำน้ำในสคริปต์ฉันหวังว่ามันจะไม่กีดกันโปรแกรมเมอร์ใหม่ แม้ว่าเอกสารเพิ่มเติมจะมีให้ฉันหวังว่ามันชัดเจนขึ้น!
Kantan
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.