23.7. استخدام خوارزميات المعالجة من وحدة التحكم¶
تتيح وحدة التحكم للمستخدمين المتقدمين زيادة إنتاجيتهم وإجراء عمليات معقدة لا يمكن إجراؤها باستخدام أي من عناصر الواجهة الرسومية الأخرى في إطار عمل المعالجة. يمكن تعريف نماذج تتضمن عدة خوارزميات باستخدام واجهة سطر الأوامر، ويمكن إضافة عمليات إضافية مثل الحلقات والجمل الشرطية لإنشاء مسارات عمل أكثر مرونة وقوة.
لا توجد وحدة تحكم خاصة بالمعالجة في QGIS، لكن جميع أوامر المعالجة متاحة بدلًا من ذلك من وحدة تحكم Python المدمجة في QGIS. وهذا يعني أنه يمكنك دمج تلك الأوامر في عملك في وحدة التحكم وربط خوارزميات المعالجة بجميع الميزات الأخرى المتاحة من هناك (بما فيها دوال واجهة QGIS البرمجية).
يمكن تحويل الشيفرة التي تنفّذها من وحدة تحكم Python، حتى لو لم تستدعِ أي دالة معالجة محددة، إلى خوارزمية جديدة يمكنك استدعاؤها لاحقًا من صندوق الأدوات أو المصمّم الرسومي للنماذج أو أي مكوّن آخر، تمامًا كما تفعل مع أي خوارزمية أخرى. في الواقع، بعض الخوارزميات التي تجدها في صندوق الأدوات هي سكربتات بسيطة.
في هذا القسم سنرى كيفية استخدام خوارزميات المعالجة من وحدة تحكم Python في QGIS، وكذلك كيفية كتابة الخوارزميات باستخدام Python.
23.7.1. استدعاء الخوارزميات من وحدة تحكم Python¶
أول ما عليك فعله هو استيراد دوال المعالجة بالسطر التالي:
>>> from qgis import processing
والآن، هناك في الأساس شيء واحد (مثير للاهتمام) يمكنك فعله بذلك من وحدة التحكم: تنفيذ خوارزمية. يتم ذلك باستخدام الدالة run()، التي تأخذ معرّف الخوارزمية المراد تنفيذها كمعاملها الأول، ثم عددًا متغيرًا من المعاملات الإضافية بحسب متطلبات الخوارزمية. لذا فأول ما تحتاج إلى معرفته هو اسم الخوارزمية المراد تنفيذها. وهذا ليس الاسم الذي تراه في صندوق الأدوات، بل اسم فريد خاص بسطر الأوامر. للعثور على الاسم الصحيح لخوارزميتك، يمكنك استخدام processingRegistry. اكتب السطر التالي في وحدة التحكم:
>>> for alg in QgsApplication.processingRegistry().algorithms():
print(alg.id(), "->", alg.displayName())
سترى شيئًا كهذا (مع إضافة بعض الشرطات الإضافية لتحسين القراءة).
3d:tessellate --------------> Tessellate
gdal:aspect ----------------> Aspect
gdal:assignprojection ------> Assign projection
gdal:buffervectors ---------> Buffer vectors
gdal:buildvirtualraster ----> Build Virtual Raster
gdal:cliprasterbyextent ----> Clip raster by extent
gdal:cliprasterbymasklayer -> Clip raster by mask layer
gdal:clipvectorbyextent ----> Clip vector by extent
gdal:clipvectorbypolygon ---> Clip vector by mask layer
gdal:colorrelief -----------> Color relief
gdal:contour ---------------> Contour
gdal:convertformat ---------> Convert format
gdal:dissolve --------------> Dissolve
...
هذه قائمة بجميع معرّفات الخوارزميات المتاحة، مرتبة حسب اسم المزوّد واسم الخوارزمية، مع الأسماء المقابلة لها.
بعد أن تعرف اسم الخوارزمية في سطر الأوامر، فالخطوة التالية هي تحديد الصياغة الصحيحة لتنفيذها. أي معرفة المعاملات المطلوبة عند استدعاء الدالة run().
توجد دالة لوصف الخوارزمية بالتفصيل، يمكن استخدامها للحصول على قائمة بالمعاملات التي تتطلبها الخوارزمية والمخرجات التي ستولّدها. للحصول على هذه المعلومات يمكنك استخدام الدالة algorithmHelp(). مرّر إليها كمعامل معرّف الخوارزمية، وليس الاسم الوصفي الكامل.
عند استدعاء الدالة مع native:buffer كمعامل (qgis:buffer اسم بديل لـ native:buffer وسيعمل أيضًا)، تحصل على الوصف التالي:
>>> processing.algorithmHelp("native:buffer")
Buffer (native:buffer)
This algorithm computes a buffer area for all the features in an
input layer, using a fixed or dynamic distance.
The segments parameter controls the number of line segments to
use to approximate a quarter circle when creating rounded
offsets.
The end cap style parameter controls how line endings are handled
in the buffer.
The join style parameter specifies whether round, miter or
beveled joins should be used when offsetting corners in a line.
The miter limit parameter is only applicable for miter join
styles, and controls the maximum distance from the offset curve
to use when creating a mitered join.
----------------
Input parameters
----------------
INPUT: Input layer
Parameter type: QgsProcessingParameterFeatureSource
Accepted data types:
- str: layer ID
- str: layer name
- str: layer source
- QgsProcessingFeatureSourceDefinition
- QgsProperty
- QgsVectorLayer
DISTANCE: Distance
Parameter type: QgsProcessingParameterDistance
Accepted data types:
- int
- float
- QgsProperty
SEGMENTS: Segments
Parameter type: QgsProcessingParameterNumber
Accepted data types:
- int
- float
- QgsProperty
END_CAP_STYLE: End cap style
Parameter type: QgsProcessingParameterEnum
Available values:
- 0: Round
- 1: Flat
- 2: Square
Accepted data types:
- int
- str: as string representation of int, e.g. '1'
- QgsProperty
JOIN_STYLE: Join style
Parameter type: QgsProcessingParameterEnum
Available values:
- 0: Round
- 1: Miter
- 2: Bevel
Accepted data types:
- int
- str: as string representation of int, e.g. '1'
- QgsProperty
MITER_LIMIT: Miter limit
Parameter type: QgsProcessingParameterNumber
Accepted data types:
- int
- float
- QgsProperty
DISSOLVE: Dissolve result
Parameter type: QgsProcessingParameterBoolean
Accepted data types:
- bool
- int
- str
- QgsProperty
OUTPUT: Buffered
Parameter type: QgsProcessingParameterFeatureSink
Accepted data types:
- str: destination vector file, e.g. 'd:/test.shp'
- str: 'memory:' to store result in temporary memory layer
- str: using vector provider ID prefix and destination URI,
e.g. 'postgres:...' to store result in PostgreSQL table
- QgsProcessingOutputLayerDefinition
- QgsProperty
----------------
Outputs
----------------
OUTPUT: <QgsProcessingOutputVectorLayer>
Buffered
لديك الآن كل ما تحتاجه لتشغيل أي خوارزمية. وكما ذكرنا سابقًا، يمكن تشغيل الخوارزميات باستخدام: run(). وصياغتها كما يلي:
>>> processing.run(name_of_the_algorithm, parameters)
حيث parameters قاموس من المعاملات يعتمد على الخوارزمية التي تريد تشغيلها، وهو بالضبط القائمة التي تعطيك إياها الدالة algorithmHelp().
1 >>> processing.run("native:buffer", {'INPUT': '/data/lines.shp',
2 'DISTANCE': 100.0,
3 'SEGMENTS': 10,
4 'DISSOLVE': True,
5 'END_CAP_STYLE': 0,
6 'JOIN_STYLE': 0,
7 'MITER_LIMIT': 10,
8 'OUTPUT': '/data/buffers.shp'})
إذا كان المعامل اختياريًا ولا تريد استخدامه، فلا تُدرجه في القاموس.
إذا لم يُحدَّد معامل، فستُستخدم القيمة الافتراضية.
تُدخَل القيم بطرق مختلفة بحسب نوع المعامل. تقدم القائمة التالية مراجعة سريعة لكيفية إدخال القيم لكل نوع من معاملات الإدخال:
طبقة شبكية أو طبقة متجهية أو جدول. استخدم ببساطة سلسلة نصية تحتوي على الاسم الذي يعرّف كائن البيانات المراد استخدامه (اسمه في جدول محتويات QGIS) أو اسم ملف (إذا لم تكن الطبقة المقابلة مفتوحة، فستُفتح لكن لن تُضاف إلى لوحة الخريطة). إذا كان لديك نسخة من كائن QGIS يمثل الطبقة، يمكنك أيضًا تمريرها كمعامل.
التعداد. إذا كان للخوارزمية معامل من نوع التعداد، فيجب إدخال قيمة ذلك المعامل كعدد صحيح. لمعرفة الخيارات المتاحة يمكنك استخدام الأمر
algorithmHelp()كما سبق. على سبيل المثال، للخوارزميةnative:bufferتعداد اسمه JOIN_STYLE:JOIN_STYLE: Join style Parameter type: QgsProcessingParameterEnum Available values: - 0: Round - 1: Miter - 2: Bevel Accepted data types: - int - str: as string representation of int, e.g. '1' - QgsPropertyفي هذه الحالة، للمعامل ثلاثة خيارات. لاحظ أن الترقيم يبدأ من الصفر.
منطقي (Boolean). استخدم
TrueأوFalse.مدخلات متعددة. القيمة سلسلة نصية تحتوي على واصفات المدخلات مفصولة بفواصل منقوطة (
;). وكما في حالة الطبقات أو الجداول المفردة، يمكن أن يكون كل واصف مدخل اسم كائن البيانات أو مسار ملفه.حقل جدول من XXX. استخدم سلسلة نصية تحتوي على اسم الحقل المراد استخدامه. هذا المعامل حساس لحالة الأحرف.
جدول ثابت. اكتب قائمة جميع قيم الجدول مفصولة بفواصل (
,) ومحاطة بعلامتي اقتباس ("). تبدأ القيم من الصف العلوي وتسير من اليسار إلى اليمين. يمكنك أيضًا استخدام مصفوفة ثنائية الأبعاد من القيم تمثل الجدول.نظام الإحداثيات المرجعي (CRS). أدخل رقم رمز EPSG لنظام الإحداثيات المرجعي المطلوب.
الامتداد. يجب أن تستخدم سلسلة نصية تحتوي على القيم
xminوxmaxوyminوymaxمفصولة بفواصل (,).
لا تحتاج المعاملات المنطقية ومعاملات الملفات والسلاسل النصية والمعاملات الرقمية إلى أي شرح إضافي.
لمعاملات الإدخال مثل السلاسل النصية والقيم المنطقية والقيم الرقمية قيم افتراضية. تُستخدم القيمة الافتراضية إذا كان إدخال المعامل المقابل مفقودًا.
بالنسبة لكائنات بيانات المخرجات، اكتب مسار الملف الذي سيُستخدم لحفظها، تمامًا كما يحدث من صندوق الأدوات. إذا لم يُحدَّد كائن المخرج، تُحفظ النتيجة في ملف مؤقت (أو تُتجاوز إذا كان مخرجًا اختياريًا). يحدد امتداد الملف صيغته. إذا أدخلت امتدادًا لا تدعمه الخوارزمية، فستُستخدم صيغة الملف الافتراضية لنوع المخرج ذلك، ويُلحق امتدادها المقابل بمسار الملف المعطى.
بخلاف تنفيذ الخوارزمية من صندوق الأدوات، لا تُضاف المخرجات إلى لوحة الخريطة إذا نفّذت الخوارزمية نفسها من وحدة تحكم Python باستخدام الدالة run(). تُرجع تلك الدالة قاموسًا مفاتيحه اسم مخرج واحد أو أكثر (الأسماء المعروضة في وصف الخوارزمية) وقيمه مسارات ملفات تلك المخرجات:
1 >>> myresult = processing.run("native:buffer", {'INPUT': '/data/lines.shp',
2 'DISTANCE': 100.0,
3 'SEGMENTS': 10,
4 'DISSOLVE': True,
5 'END_CAP_STYLE': 0,
6 'JOIN_STYLE': 0,
7 'MITER_LIMIT': 10,
8 'OUTPUT': '/data/buffers.shp'})
9 >>> myresult['OUTPUT']
10 /data/buffers.shp
يمكنك بعد ذلك تحميل المخرج في المشروع كأي طبقة عادية:
1 >>> buffered_layer = myresult['OUTPUT']
2 >>> QgsProject.instance().addMapLayer(buffered_layer)
لتحميل مخرجات المعالجة في المشروع فورًا، يمكنك استخدام الدالة runAndLoadResults() بدلًا من run().
1 >>> processing.runAndLoadResults("native:buffer", {parameters:values})
إذا أردت فتح نافذة حوار خوارزمية من وحدة التحكم، يمكنك استخدام الدالة createAlgorithmDialog. المعامل الإلزامي الوحيد هو معرّف الخوارزمية، لكن يمكنك أيضًا تعريف قاموس المعاملات بحيث تُملأ نافذة الحوار تلقائيًا:
1 >>> my_dialog = processing.createAlgorithmDialog("native:buffer", {
2 'INPUT': '/data/lines.shp',
3 'DISTANCE': 100.0,
4 'SEGMENTS': 10,
5 'DISSOLVE': True,
6 'END_CAP_STYLE': 0,
7 'JOIN_STYLE': 0,
8 'MITER_LIMIT': 10,
9 'OUTPUT': '/data/buffers.shp'})
10 >>> my_dialog.show()
تفتح الدالة execAlgorithmDialog نافذة الحوار فورًا:
1 >>> processing.execAlgorithmDialog("native:buffer", {
2 'INPUT': '/data/lines.shp',
3 'DISTANCE': 100.0,
4 'SEGMENTS': 10,
5 'DISSOLVE': True,
6 'END_CAP_STYLE': 0,
7 'JOIN_STYLE': 0,
8 'MITER_LIMIT': 10,
9 'OUTPUT': '/data/buffers.shp'})
23.7.2. إنشاء السكربتات وتشغيلها من صندوق الأدوات¶
يمكنك إنشاء خوارزمياتك الخاصة بكتابة شيفرة Python. تمتد سكربتات المعالجة من الصنف QgsProcessingAlgorithm، لذا تحتاج إلى إضافة بعض أسطر الشيفرة الإضافية لتنفيذ الدوال الإلزامية. تجد Create new script (صفحة فارغة) و Create New Script from Template (قالب يتضمن شيفرة الدوال الإلزامية لـ QgsProcessingAlgorithm) ضمن القائمة المنسدلة Scripts أعلى صندوق أدوات المعالجة. سيُفتح محرر سكربتات المعالجة، وهناك يجب أن تكتب شيفرتك. حفظ السكربت من هناك في المجلد scripts (المجلد الافتراضي عند فتح نافذة حوار حفظ الملف) بالامتداد .py يُفترض أن ينشئ الخوارزمية المقابلة.
يُعرَّف اسم الخوارزمية (الذي ستراه في صندوق الأدوات) داخل الشيفرة.
لنلقِ نظرة على الشيفرة التالية، التي تعرّف خوارزمية معالجة تُجري عملية نطاق عازل بمسافة يحددها المستخدم على طبقة متجهية يحددها المستخدم، بعد تنعيم الطبقة أولًا.
1from qgis.core import (QgsProcessingAlgorithm,
2 QgsProcessingParameterNumber,
3 QgsProcessingParameterFeatureSource,
4 QgsProcessingParameterFeatureSink)
5
6from qgis import processing
7
8class algTest(QgsProcessingAlgorithm):
9 INPUT_BUFFERDIST = 'BUFFERDIST'
10 OUTPUT_BUFFER = 'OUTPUT_BUFFER'
11 INPUT_VECTOR = 'INPUT_VECTOR'
12
13 def __init__(self):
14 super().__init__()
15
16 def name(self):
17 return "algTest"
18
19 def displayName(self):
20 return "algTest script"
21
22 def createInstance(self):
23 return type(self)()
24
25 def initAlgorithm(self, config=None):
26 self.addParameter(QgsProcessingParameterFeatureSource(
27 self.INPUT_VECTOR, "Input vector"))
28 self.addParameter(QgsProcessingParameterNumber(
29 self.INPUT_BUFFERDIST, "Buffer distance",
30 QgsProcessingParameterNumber.Double,
31 100.0))
32 self.addParameter(QgsProcessingParameterFeatureSink(
33 self.OUTPUT_BUFFER, "Output buffer"))
34
35 def processAlgorithm(self, parameters, context, feedback):
36 #DO SOMETHING
37 algresult = processing.run("native:smoothgeometry",
38 {'INPUT': parameters[self.INPUT_VECTOR],
39 'ITERATIONS':2,
40 'OFFSET':0.25,
41 'MAX_ANGLE':180,
42 'OUTPUT': 'memory:'},
43 context=context, feedback=feedback, is_child_algorithm=True)
44 smoothed = algresult['OUTPUT']
45 algresult = processing.run('native:buffer',
46 {'INPUT': smoothed,
47 'DISTANCE': parameters[self.INPUT_BUFFERDIST],
48 'SEGMENTS': 5,
49 'END_CAP_STYLE': 0,
50 'JOIN_STYLE': 0,
51 'MITER_LIMIT': 10,
52 'DISSOLVE': True,
53 'OUTPUT': parameters[self.OUTPUT_BUFFER]},
54 context=context, feedback=feedback, is_child_algorithm=True)
55 buffered = algresult['OUTPUT']
56 return {self.OUTPUT_BUFFER: buffered}
بعد إجراء عمليات الاستيراد اللازمة، تُحدَّد دوال QgsProcessingAlgorithm التالية:
name(): معرّف الخوارزمية (بأحرف صغيرة).displayName(): اسم مقروء للخوارزمية.createInstance(): تُنشئ نسخة جديدة من صنف الخوارزمية.initAlgorithm(): تهيئ parameterDefinitions و outputDefinitions.هنا تصف معاملات الخوارزمية ومخرجها. في هذه الحالة: مصدر معالم للإدخال، ومستقبِل معالم (feature sink) للنتيجة، ورقم لمسافة النطاق العازل.
processAlgorithm(): تنجز العمل.هنا نشغّل أولًا الخوارزمية
smoothgeometryلتنعيم الشكل الهندسي، ثم نشغّل الخوارزميةbufferعلى المخرج المنعَّم. لكي نتمكن من تشغيل خوارزميات من داخل خوارزمية أخرى، يجب أن نضبط الوسيطis_child_algorithmعلىTrue. يمكنك أن ترى كيف تُستخدم معاملات الإدخال والإخراج كمعاملات للخوارزميتينsmoothgeometryوbuffer.
تتوفر أنواع مختلفة عديدة من المعاملات للإدخال والإخراج. تجد القائمة الكاملة في أنواع المدخلات والمخرجات لخوارزميات المعالجة.
المعامل الأول للمُنشئات هو اسم المعامل، والثاني هو وصف المعامل (لواجهة المستخدم). بقية معاملات المُنشئ خاصة بنوع المعامل.
يمكن تحويل المدخلات إلى أصناف QGIS باستخدام دوال parameterAs… في QgsProcessingAlgorithm. على سبيل المثال، للحصول على الرقم المقدَّم لمسافة النطاق العازل كعدد عشري مزدوج (double):
self.parameterAsDouble(parameters, self.INPUT_BUFFERDIST, context)).
يجب أن تُرجع الدالة processAlgorithm() قاموسًا يحتوي على قيم لكل مخرج تعرّفه الخوارزمية. يتيح ذلك الوصول إلى هذه المخرجات من خوارزميات أخرى، بما فيها الخوارزميات الأخرى الموجودة ضمن النموذج نفسه.
يجب أن تعرّف الخوارزميات الجيدة التصميم وتُرجع أكبر عدد معقول من المخرجات. المخرجات غير المعالمية، مثل الأرقام والسلاسل النصية، مفيدة جدًا عند تشغيل خوارزميتك كجزء من نموذج أكبر، لأنه يمكن استخدام هذه القيم كمعاملات إدخال للخوارزميات اللاحقة ضمن النموذج. فكّر في إضافة مخرجات رقمية لأمور مثل عدد المعالم المعالَجة، وعدد المعالم غير الصالحة التي صودفت، وعدد المعالم الناتجة، وغيرها. كلما زادت المخرجات التي تُرجعها، زادت فائدة خوارزميتك!
23.7.2.1. التغذية الراجعة¶
يجب استخدام الكائن feedback المُمرَّر إلى processAlgorithm() للتغذية الراجعة إلى المستخدم والتفاعل معه. يمكنك استخدام الدالة setProgress() للكائن feedback لتحديث شريط التقدم (من 0 إلى 100) لإعلام المستخدم بتقدم الخوارزمية. هذا مفيد جدًا إذا كانت خوارزميتك تستغرق وقتًا طويلًا لإكمالها.
يوفّر الكائن feedback الدالة isCanceled() التي يجب مراقبتها لتمكين المستخدم من إلغاء الخوارزمية. يمكن استخدام الدالة pushInfo() للكائن feedback لإرسال معلومات إلى المستخدم، والدالة reportError() مفيدة لإبلاغ المستخدمين بالأخطاء غير القاتلة.
يجب أن تتجنب الخوارزميات استخدام أشكال أخرى لتقديم التغذية الراجعة للمستخدمين، مثل تعليمات print أو التسجيل في QgsMessageLog، وأن تستخدم دائمًا كائن التغذية الراجعة بدلًا من ذلك. يتيح ذلك تسجيلًا مفصلًا للخوارزمية، كما أنه آمن مع الخيوط (thread-safe)، وهذا مهم لأن الخوارزميات تُشغَّل عادةً في خيط في الخلفية.
23.7.2.2. معالجة الأخطاء¶
إذا واجهت خوارزميتك خطأً يمنعها من التنفيذ، مثل قيم إدخال غير صالحة أو حالة أخرى لا يمكنها أو لا ينبغي لها التعافي منها، فيجب أن تُطلق استثناء QgsProcessingException. مثلًا:
if feature['value'] < 20:
raise QgsProcessingException('Invalid input value {}, must be >= 20'.format(feature['value']))
حاول تجنب إطلاق QgsProcessingException للأخطاء غير القاتلة (مثلًا عندما يكون للمعلم شكل هندسي فارغ)، وبدلًا من ذلك أبلغ عن هذه الأخطاء عبر feedback.reportError() وتجاوز المعلم. يساعد ذلك على جعل خوارزميتك "ملائمة للنماذج"، إذ يتجنب إيقاف تنفيذ خوارزمية كاملة عند مصادفة خطأ غير قاتل.
23.7.2.3. توثيق سكربتاتك¶
كما في حالة النماذج، يمكنك إنشاء توثيق إضافي لسكربتاتك لشرح ما تفعله وكيفية استخدامها.
يوفّر QgsProcessingAlgorithm الدوال helpString() و shortHelpString() و helpUrl() لهذا الغرض. حدّد هذه الدوال أو أعد تعريفها لتقديم مزيد من المساعدة للمستخدم.
تُستخدم shortDescription() في التلميح الذي يظهر عند تمرير المؤشر فوق الخوارزمية في صندوق الأدوات.
23.7.3. خطافات السكربتات قبل التنفيذ وبعده¶
يمكن أيضًا استخدام السكربتات كخطافات (hooks) تُشغَّل قبل تشغيل الخوارزمية وبعده على الترتيب. يمكن استخدام ذلك لأتمتة المهام التي يجب تنفيذها كلما نُفّذت خوارزمية.
الصياغة مطابقة للصياغة الموضّحة أعلاه، لكن يتوفر متغير عام إضافي اسمه alg يمثّل الخوارزمية التي نُفّذت للتو (أو التي على وشك التنفيذ).
في مجموعة General ضمن نافذة حوار خيارات المعالجة، ستجد مدخلين باسم Pre-execution script و Post-execution script يمكنك فيهما إدخال أسماء ملفات السكربتات التي ستُشغَّل في كل حالة.