Scriptare în Python pentru Cadrul de Procesare

Atenționare

O nouă versiune a acestui tutorial este disponibilă la Scriptare în Python pentru Cadrul de Procesare (QGIS3)

Se pot crea script-uri pyqgis independente, care pot fi executate prin intermediul Consolei Python din QGIS. Cu puține modificări, puteți rula script-urile prin intermediul Cadrului de Procesare. Acest lucru are mai multe avantaje. În primul rând, preluarea datelor de la utilizator și scrierea fișierelor de ieșire este mult mai ușoară, deoarece Cadrul de Procesare oferă o interfață de utilizator standardizată pentru acestea. În al doilea rând, având script-ul în Bara de Instrumente de Procesare, este posibil ca acesta să facă parte din orice Model de Procesare sau să ruleze în serie, pentru mai multe intrări. Acest tutorial vă arată cum să scrieți un script Python personalizat, care să facă parte din Cadrul de Procesare din QGIS.

Privire de ansamblu asupra activității

Script-ul nostru va efectua o operație de dizolvare bazată pe un câmp ales de utilizator. De asemenea, va însuma valorile altui câmp pentru entitățile dizolvate. În cadrul exemplului vom dizolva un fișier shape al lumii în funcție de atributul SUBREGIUNE, apoi vom însuma câmpul POP_EST pentru a calcula totalul populației din regiunea dizolvată.

Notă

Dacă doriți să știți cum se face o operație de dizolvare împreună cu Statisticile, puteți folosi excelentul plugin DissolveWithStats. Acest script este o demonstrație despre cum să puneți în aplicare o funcționalitate similară prin intermediul unui script de Procesare.

Obținerea datelor

Vom folosi setul de date Admin 0 - Țări de la Natural Earth.

Vom folosi setul de date Admin 0 - fișierul shape al țărilor.

Sursa de date [NATURALEARTH]

Pentru comoditate, puteți descărca o copie a setului de date direct de la adresa de mai jos:

ne_10_admin_0_countries.zip

Procedura

  1. În QGIS, mergeți la Layers ‣ Add Vector ‣ Add Vector Layer. Navigați la fișierul descărcat ne_10_admin_0_countries.zip și încărcați stratul ne_10_admin_0_countries. Mergeți la Processing ‣ Toolbox.

../_images/1202.png
  1. Extinteți grupul Scripts din Processing Toolbox și selectați Create a new script.

../_images/2167.png
  1. Pentru ca un script Python să fie recunoscut ca un script de Procesare, la începutul script-ului trebuie să se afle specificațiile de intrare și de ieșire. Acestea vor fi utilizate la construirea interfeței cu utilizatorul, pentru a rula script-ul. Puteți afla mai multe despre formatul acestor linii, din Documentația Processing din QGIS. Introduceți următoarele linii în Script editor. Aici avem 3 intrări ale utilizatorului: dissolve_layer, dissolve_field și sum_field. Rețineți că dissolve_layer se adaugă după definițiile ambelor câmpuri de intrare. Acest lucru înseamnă că intrările vor fi pre-populate prin alegerea câmpurilor din dissolve_layer. De asemenea, specificați output_layer ca și strat vectorial de ieșire. Faceți clic pe butonul Save.

##dissolve_layer=vector
##dissolve_field=field dissolve_layer
##sum_field=field dissolve_layer
##output_layer=output vector
../_images/3106.png
  1. Denumiți script-ul dissolve_with_sum și salvați-l în locația implicită din folderul .qgis2 ‣ processing ‣ scripts.

../_images/468.png
  1. Înapoi, în Script editor, faceți clic pe butonul Run algorithm, pentru a previzualiza interfața utilizatorului.

../_images/562.png
  1. Puteți vedea că doar prin adăugarea a câtorva rânduri, avem o interfață frumoasă, pe care utilizatorul va preciza intrările. De asemenea, este în concordanță cu toți ceilalți algoritmi de procesare, astfel încât nu există nici o curbă de învățare implicată în folosirea algoritmului personalizat.

../_images/659.png
  1. În: guilabel: Script editor, introduceți următorul cod. Veți observa că apelăm unele metode speciale, cum ar fi processing.getObject() și processing.features(). Acestea sunt ambalate confortabil, pentru a ușura lucrul cu datele. Puteți afla mai multe despre acestea din secțiunea Funcțiilor suplimentare de manipulare a datelor a Documentației de Procesare QGIS. Clic pe Save pentru a salva codul nou introdus, și apoi pe butonul X pentru a închide editorul.

Notă

Acest script folosește în mod extensiv comprehensiunea listelor python. Aruncați o privire la acest tutorial pentru a înțelege listele comprehensive, și pentru a vă familiariza cu sintaxa.

from qgis.core import *
from PyQt4.QtCore import *

inlayer = processing.getObject(dissolve_layer)
dissolve_field_index = inlayer.fieldNameIndex(dissolve_field)
sum_field_index = inlayer.fieldNameIndex(sum_field)

# Find unique values present in the dissolve field
unique_values = set([f[dissolve_field] for f in
processing.features(inlayer)])

print unique_values
../_images/758.png
  1. În timp ce se scrie codul, este important să fiți în măsură să vedeți erorile și să depanați codul. Script-urile de Procesare pot fi depanate cu ușurință prin intermediul consolei Python încorporate. În fereastra principală a QGIS, mergeți la Plugins ‣ Python Console. O dată ce consola este deschisă, găsiți script-ul în Instrumentarul Processing și faceți dublu clic pe el pentru a-l lansa.

../_images/856.png
  1. Selectați SUBREGIUNE ca și câmp de dizolvare. Puteți alege orice câmp și ca câmp de însumare atât timp cât scriptul nu are nici un cod pentru a interacționa cu acesta. Clic Run.

../_images/955.png
  1. Veți vedea un dialog de eroare. Acest lucru este de așteptat, deoarece script-ul este incomplet și nu generează nici o ieșire încă.

../_images/1063.png
  1. În principalele ferestrele QGIS, veți vedea ieșirea de depanare a script-ului afișat în consolă. Acest lucru este un mod util de a adăuga instrucțiuni de imprimare și de a vedea valorile variabile intermediare.

../_images/11102.png
  1. Să ne întoarcem la editarea script-ului printr-un clic dreapta pe script, apoi selectați Edit script.

../_images/1264.png
  1. Introduceți codul de mai jos pentru a finaliza script-ul. Rețineți că folosim algoritmul existent de dizolvare din QGIS, prin procesarea cu ajutorul metodei processing.runalg().

# Create a dictionary to hold values from the sum field
sum_unique_values = {}
attrs = [f.attributes() for f in processing.features(inlayer)]

for unique_value in unique_values:
    val_list = [ f_attr[sum_field_index] for f_attr in attrs if f_attr[dissolve_field_index] == unique_value]
    sum_unique_values[unique_value] = sum(val_list)

# Run the regular Dissolve algorithm
processing.runalg("qgis:dissolve", dissolve_layer, "false",
    dissolve_field, output_layer)

# Add a new attribute called 'SUM' in the output layer
outlayer = processing.getObject(output_layer)
provider = outlayer.dataProvider()
provider.addAttributes([QgsField('SUM', QVariant.Double)])
outlayer.updateFields()

# Set the value of the 'SUM' field for each feature
outlayer.startEditing()
new_field_index = outlayer.fieldNameIndex('SUM')
for f in processing.features(outlayer):
  outlayer.changeAttributeValue(f.id(), new_field_index, sum_unique_values[f[dissolve_field]])
outlayer.commitChanges()
../_images/1361.png
  1. Rulează algoritmul prin selectarea SUBREGIUNII ca și câmp dizolvat, și POP_EST ca și câmp însumat. Clic pe Run.

Notă

Algoritmul de procesare poate dura până la 10 minute pentru a termina, în funcție de sistemul dumneavoastră.

../_images/1458.png
  1. După ce prelucrarea se încheie, puteți folosi instrumentul de Identificare, pentru a efectua clic pe orice poligon. Veți vedea adăugat noul câmp, SUM, cu valorile POP_EST adăugate din toate poligoanele originale.

../_images/1554.png
  1. Veți observa că toate celelalte câmpuri ale rezultatului sunt încă prezente. Când se dizolvă mai multe entități pentru a crea o singură entitate, nu are sens să se păstreze câmpurile originale în rezultat. Mergeți înapoi la: guilabel: Script editor și adăugați următorul cod pentru a șterge toate domeniile, cu excepția câmpului SUM și a câmpului care a fost folosit pentru a dizolva stratul original. Faceți clic pe butonul Save și închideți fereastra.

# Delete all fields except dissolve field and the newly created 'SUM' field.
outlayer.startEditing()

fields_to_delete = [fid for fid in range(len(provider.fields())) if fid != new_field_index and fid != dissolve_field_index]
provider.deleteAttributes(fields_to_delete)
outlayer.updateFields()

outlayer.commitChanges()
../_images/1651.png
  1. Una dintre funcționalitățile ascunse ale Cadrului de Procesare este aceea că toți algoritmii pot lucra pe entitățile selectate ale unui strat. Acest lucru este foarte util atunci când doriți să rulați un algoritm pe subsetul unui strat. Deoarece script-ul nostru folosește metoda processing.features() pentru a citi entitățile, se va respecta selecția curentă. Pentru a demonstra aceasta, haideți să facem mai întâi o selecție. Faceți clic pe butonul Selectare entități utilizând o expresie.

../_images/1748.png
  1. Introduceți următoarea expresie pentru a selecta entitățile din America de Nord și cea din Sud, apoi faceți clic pe Select.

"CONTINENT" = 'North America' OR "CONTINENT" = 'South America'
../_images/1845.png
  1. Veți vedea entitățile selectate, evidențiate cu galben. Efectuați clic-dreapta pe script-ul dissolve_with_sum, apoi selectați Execute.

../_images/1937.png
  1. Selectați intrările ca mai înainte, apoi efectuați clic pe Run.

../_images/2032.png
  1. Un nou strat de ieșire va fi adăugat în QGIS. Acesta va conține geometriile dizolvate numai din entitățile selectate din stratul de intrare. Observați, de asemenea, că stratul de ieșire va conține numai 2 câmpuri, cum era de asteptat.

../_images/2168.png
  1. O ultimă, dar importantă activitate, o reprezintă documentarea algoritmului nostru. Cadrul de Procesare dispune de instrumente plăcute pentru a scrie și accesa Ajutorul. Mergeți la Script editor și faceți clic pe butonul Edit script help.

../_images/2232.png
  1. Completați detaliile pentru diferite elemente și faceți clic pe OK. Un ajutor detaliat va fi disponibil pentru toți utilizatorii script-ului în fila Help, atunci când se va lansa algoritmul.

../_images/2329.png

Mai jos este script-ul complet. Îl puteți modifica pentru a se potrivi cerințelor dumneavoastră.

##dissolve_layer=vector
##dissolve_field=field dissolve_layer
##sum_field=field dissolve_layer
##output_layer=output vector

from qgis.core import *
from PyQt4.QtCore import *

inlayer = processing.getObject(dissolve_layer)
dissolve_field_index = inlayer.fieldNameIndex(dissolve_field)
sum_field_index = inlayer.fieldNameIndex(sum_field)

# Find unique values present in the dissolve field
unique_values = set([f[dissolve_field] for f in processing.features(inlayer)])

# Create a dictionary to hold values from the sum field
sum_unique_values = {}
attrs = [f.attributes() for f in processing.features(inlayer)]
 
for unique_value in unique_values:
    val_list = [ f_attr[sum_field_index] for f_attr in attrs if f_attr[dissolve_field_index] == unique_value]
    sum_unique_values[unique_value] = sum(val_list)

# Run the regular Dissolve algorithm
processing.runalg("qgis:dissolve", dissolve_layer, "false",
    dissolve_field, output_layer)

# Add a new attribute called 'SUM' in the output layer
outlayer = processing.getObject(output_layer)
provider = outlayer.dataProvider()
provider.addAttributes([QgsField('SUM', QVariant.Double)])
outlayer.updateFields()

# Set the value of the 'SUM' field for each feature
outlayer.startEditing()
new_field_index = outlayer.fieldNameIndex('SUM')
for f in processing.features(outlayer):
  outlayer.changeAttributeValue(f.id(), new_field_index, sum_unique_values[f[dissolve_field]])
outlayer.commitChanges()

# Delete all fields except dissolve field and the newly created 'SUM' field
outlayer.startEditing()
fields_to_delete = [fid for fid in range(len(provider.fields())) if fid != new_field_index and fid != dissolve_field_index]
provider.deleteAttributes(fields_to_delete)
outlayer.updateFields()
outlayer.commitChanges()

If you want to give feedback or share your experience with this tutorial, please comment below. (requires GitHub account)