Python


Tworzenie skryptów Pythona w QGIS za pomocą narzędzi geoprocesingu

Wtyczka Processing (do wersji QGIS 1.8 SEXTANTE) zawiera wiele pomocnych narzędzi usprawniających pracę z danymi przestrzennymi w QGIS. Jednym z nich jest mechanizm pozwalający na tworzenie i uruchamianie przez użytkowników skryptów napisanych w języku programowania Python. Dzięki temu aby dodać nową funkcjonalność nie trzeba tworzyć nowej wtyczki, a przy tym martwić się o zbudowanie interfejsu, właściwe wypełnienie metadanych itp. Skrypty traktowane są przez Processing w ten sam sposób jak pozostałe algorytmy. Można je więc uruchomić w oknie dialogowym lub w trybie wsadowym jak również wykorzystać w graficznym modelarzu. Co więcej, w skryptach można wykorzystać już istniejące algorytmy.

Edytor skryptu

Aby stworzyć nowy skrypt należy w oknie Narzędzia geoprocessingu rozwinąć pozycję Scripts ->Tools i podwójnie kliknąć na Create new script. Zostanie wyświetlony edytor skryptu. Posiada on kilka funkcji ułatwiających pisanie kodu źródłowego jak kolorowanie i autouzupełnianie składni, zwijanie/rozwijanie bloków kodu czy numerowanie linii. W górnej części okna dostępne są przyciski umożliwiające m.in. zapis zmian, edycję pomocy czy uruchomienie skryptu.

edytor

Tworzenie skryptu

Definiowanie danych wejściowych

Na początku kodu można określić nazwę grupy, w której będzie wyświetlany skrypt w oknie Narzędzi geoprocessingu:

[code lang=”python”]##Nazwa grupy=group[/code]

Jeśli sami nie określimy grupy to skrypt zostanie przypisany do grupy User scripts.

Następnie należy określić pola do wprowadzania przez użytkownika niezbędnych parametrów. Każdy parametr określa się w jednej linii zaczynającej się znakami ##, następnie należy podać jego nazwę, typ danych oraz, w niektórych przypadkach, opcje:

[code lang=”python”]##nazwa_zmiennej=typ_danych [opcje][/code]

Nazwy zmiennych nie powinny zawierać spacji – zamiast niej należy wpisać podkreślnik – wtyczka automatycznie zamieni go w spację. Nie należy również korzystać ze znaków specjalnych, w tym polskich znaków diakrytycznych. Opcje pozwalają m.in. na ustawienie domyślnych wartości lub typu geometrii warstwy wektorowej, w większości przypadków nie są one jednak wymagane. Należy je oddzielić od typu danych pojedynczą spacją. Aktualnie dostępne są następujące typy danych:

  1. raster – pole wyboru umożliwiające wybór jednej z wczytanych do QGIS warstw rastrowych lub wskazanie pliku na dysku;
  2. vector – jw. z tym że dotyczy warstw wektorowych. Domyślnie dostępne są wszystkie rodzaje warstw, jednak istnieje możliwość określenia rodzaju geometrii poprzez ustawienie odpowiedniej opcji: point, line, polygon. Przykładowo w celu ograniczenia wyboru użytkownika do warstw punktowych należy wpisać:
    [code lang=”python” gutter=”false”]##warstwa_punktowa=vector point[/code]
  3. table – pole wyboru z tabelami, wyświetlane są warstwy wektorowe jak i tabele nieprzestrzenne (pliki CSV, excel);
  4. field – pole wyboru z polami z tabeli atrybutów danej warstwy wektorowej lub tabeli. Warstwę określa się poprzez podanie jej nazwy jako opcji np.:
    [code lang=”python”]##warstwa=vector
    ##pole_tabeli=field warstwa[/code]
  5. multiple raster i multiple vector – umożliwiają jednoczesny wybór więcej niż jednej warstwy;
  6. selection – pole wyboru ze zdefiniowanymi elementami, kolejne pozycje należy rozdzielić średnikiem:
    [code lang=”python” gutter=”false”]##typ_dzialki=selection budowlana;rolnicza;woda powierzchniowa;nieznany[/code]
  7. 
    

    selection

  8. boolean – wybór wartości logicznej prawda/fałsz (tak/nie);
  9. number – wartość liczbowa, jako opcję można podać wartość domyślną np.:
    [code lang=”python” gutter=”false”]##liczba=number 4
    ##liczba_rzeczywista=number 2.5[/code]

    Liczby rzeczywiste należy podawać z kropką;

  10. string – dowolny łańcuch znaków, podobnie jak przy liczbie można określić wartość domyślną;
  11. extent – zakres geograficzny (Xmin, Xmax, Ymin, Ymax);
  12. crs – wybór układu współrzędnych, domyślnym układem jest WGS 84, ale można to zmienić ustawiając opcję parametru np.:
    [code lang=”python” gutter=”false”]##uklad=crs EPSG:2180[/code]
  13. file – wybór dowolnego pliku z dysku;
  14. folder – jw. ale wybór katalogu;

Tak przedstawiają się powyższe kontrolki w oknie skryptu:

cale_okno - Kopia

Określanie danych wyjściowych

Dane wyjściowe określa się w taki samo sposób jak wejściowe. Jako typ danych należy podać output, natomiast jako opcję należy wpisać wybrany rodzaj:

  1. output raster – warstwa rastrowa;
  2. output vector – warstwa wektorowa;
  3. output table – tabela;
  4. output html – format HTML;
  5. output file – plik;
  6. output number – liczba;
  7. output string – łańcuch znaków.

[code lang=”python”]##warstwa_wyjsciowa=output vector
##liczba_iteracji=output number[/code]

Skrypt może mieć określonych wiele danych wyjściowych. Wartości przyjmowane przez zmienne wyjściowe to, w zależności od ich rodzaju, ścieżka dostępu do pliku (1-5), liczba (6) lub łańcuch znaków (7).

Funkcje pomocnicze

Dostęp do parametrów określonych przez użytkownika odbywa się poprzez odwołanie do zmiennej za pomocą zdefiniowanej na początku nazwy (stąd zakaz korzystania w nazwach zmiennych ze spacji i znaków specjalnych). Część danych jak liczby czy łańcuchy znaków są określone wprost tzn. w formie podanej w oknie skryptu. Aby mieć dostęp do pozostałych można skorzystać z dodatkowych funkcji udostępnianych przez wtyczkę Processing które ułatwiają pracę z danymi wejściowymi:

  • getObject(str) – zwraca klasę reprezentującą w QGIS warstwę (QgsVectorLayer lub QgsRasterLayer), jako parametr może przyjmować warstwę wskazaną przez użytkownika;
  • features(layer) – zwraca iterator po obiektach danej warstwy;
    [notice]Jeśliw opcjach Geoprocesingu zaznaczona jest opcja Use only selected features to zostaną zwrócone tylko zaznaczone obiekty. Jeśli nie ma zaznaczenia to iteracja odbędzie się po wszystkich obiektach.[/notice]
  • values(layer, field1, field2, …) – zwraca słownik, w którym kluczem jest nazwa pola z tabeli atrybutów, a wartość to lista wszystkich wartości z tego pola (obsługuje tylko wartości numeryczne!);
  • uniqueValues(layer, field) – zwraca listę unikalnych wartości z pola w tabeli atrybutów.

Poniższy przykład pozwala zapisać do pliku tekstowego unikalne wartości z tabeli atrybutów warstwy wektorowej:

[code lang=”python”]##input=vector
##pole=field input
##plik=output file
wektor = processing.getObject(input)
wartosci = processing.uniqueValues(wektor, pole)
f = open(plik, 'w’)
try:
for wartosc in wartosci:
f.write(’%s\n’ % str(wartosc))
finally:
f.close()
[/code]

  1. Zdefiniowanie warstwy wejściowej. Zmienna input przechowuje ścieżkę dostępu do warstwy.
  2. Wybór przez użytkownika pola z tabeli atrybutów wybranej warstwy.
  3. Plik, do którego zostaną zapisane dane.
  4. Pobranie wskaźnika do warstwy wejściowej (klasa QgsVectorLayer).
  5. Pobranie unikalnych wartości z wybranego pola tabeli atrybutów.
  6. Otwarcie pliku do zapisu.
  7. Zabezpieczenie przed błędem w trakcie zapisu.
  8. Iteracja po pobranych wartościach.
  9. Zapis wartości do pliku, dane konwertowane są do łańcucha znaków.
  10. Po zakończeniu…
  11. … zamknięcie pliku.

Drugą grupą funkcji pomocniczych są funkcje pozwalające tworzyć nowe warstwy rastrowe, wektorowe i tabele. Znajdują się one w module processing.core.

  • VectorWriter(warstwa_wyjsciowa,kodowanie_znakow,pola,typ_geometrii,uklad_wspolrzednych)
  • RasterWriter(warstwa_wyjsciowa, minX, minY, maxX, maxY, rozmiar_komorki, liczba_kanalow, uklad_wspolrzednych)
  • TableWriter(tabela_wyjsciowa,kodowanie_znakow,pola)

[code lang=”python”]##input=vector
##output=output vector
from processing.core.VectorWriter import VectorWriter
vectorLayer = processing.getObject(input)
writer = VectorWriter(output, vectorLayer.dataProvider().encoding(), vectorLayer.pendingFields(),vectorLayer.wkbType(), vectorLayer.crs())
features = processing.features(vectorLayer)
for feat in features:
writer.addFeature(feat)
del writer[/code]

  1. Zdefiniowanie warstwy wejściowej.
  2. Definicja warstwy wyjściowej, zmienna output również przechowuje ścieżkę do pliku.
  3. Import klasy VectorWriter do stworzenia nowej warstwy na dysku.
  4. vectorLayer przechowuje instancję klasy QgsVectorLayer.
  5. Stworzenie pliku na dysku, większość parametrów pobrana jest z warstwy wejściowej.
  6. Stworzenie iteratora po obiektach warstwy.
  7. Pętla po obiektach warstwy.
  8. Dodanie obiektu do nowej warstwy.
  9. Zamknięcie pliku nowej warstwy.

Wykorzystanie istniejących algorytmów

Istnieje również możliwość wykorzystania dostępnych algorytmów wtyczki Processing. W tym celu należy wywołać funkcję runalg z odpowiednimi parametrami:

[code lang=”python”]##input_raster=raster
##input_wektor=vector
##warstwa_wyjsciowa=output vector

wektor = processing.getObject(input_wektor)
raster = processing.getObject(input_raster)
processing.runalg(’qgis:pointsfromlines’, raster, wektor, warstwa_wyjsciowa)[/code]

W powyższym przykładzie zmienne raster i wektor to odpowiednio instancje klas QgsRasterLayer i QgsVectorLayer uzyskane dzięki funkcji getObject.
W jaki sposób można uzyskać informacje o algorytmach? I w tym przypadku z pomocą przychodzi wtyczka Processing. Najprościej jest z nich korzystać za pomocą Konsoli Pythona QGIS.
Funkcja alglist wyświetla wszystkie dostępne algorytmy:

[code lang=”python”]>>> processing.alglist()
Add autoincremental field—————>qgis:addautoincrementalfield
Add field to attributes table———–>qgis:addfieldtoattributestable
Advanced Python field calculator——–>qgis:advancedpythonfieldcalculator
Basic statistics for numeric fields—–>qgis:basicstatisticsfornumericfields
Basic statistics for text fields——–>qgis:basicstatisticsfortextfields
Clip————————————>qgis:clip
…[/code]

Po lewej stronie wyświetlany jest krótki opis algorytmu, a po prawej stronie jego nazwa, którą należy użyć jako pierwszy parametr funkcji runlag. Możliwe jest ograniczenie wyników poprzez podanie tekstu (fragmentu nazwy lub opisu) jako parametru funkcji alglist() np.:

[code lang=”python”]>>> processing.alglist(’buffer’)
Fixed distance buffer——————->qgis:fixeddistancebuffer
Variable distance buffer—————->qgis:variabledistancebuffer
Grid buffer—————————–>saga:gridbuffer
Grid proximity buffer——————->saga:gridproximitybuffer
…[/code]

Aby uzyskać szczegółowe informacje odnośnie konkretnego algorytmu należy skorzystać z funkcji alghelp np.:

[code lang=”python”]>>> processing.alghelp(’qgis:fixeddistancebuffer’)
ALGORITHM: Fixed distance buffer
INPUT
DISTANCE
SEGMENTS
DISSOLVE
OUTPUT [/code]

Funkcja ta wyświetla opis algorytmu oraz jego parametry. Jeśli algorytm ma parametry typu <ParameterSelection>, czyli wybór z góry określonych opcji, dodatkowo na końcu znajduje się spis dostępnych wartości.

[code lang=”python”]&gt;&gt;&gt; processing.alghelp(&quot;saga:slopeaspectcurvature&quot;)
ALGORITHM: Slope, aspect, curvature
ELEVATION
METHOD
SLOPE
ASPECT
CURV
HCURV
VCURV

METHOD(Method)
0 – [0] Maximum Slope (Travis et al. 1975)
1 – [1] Maximum Triangle Slope (Tarboton 1997)
2 – [2] Least Squares Fitted Plane (Horn 1981, Costa-Cabral &amp; Burgess 1996)
3 – [3] Fit 2.Degree Polynom (Bauer, Rohdenburg, Bork 1985)
4 – [4] Fit 2.Degree Polynom (Heerdegen &amp; Beran 1982)
5 – [5] Fit 2.Degree Polynom (Zevenbergen &amp; Thorne 1987)
6 – [6] Fit 3.Degree Polynom (Haralick 1983)[/code]

Opcje te można wylistować również funkcją algoptions(nazwa_algorytmu). Aby je ustawić należy podać numer danej opcji według kolejności:

[code lang=”python” gutter=”false”]processing.runlag(&quot;saga:slopeaspectcurvature&quot;, raster, 1, nachylenie, …)[/code]

W powyższym przykładzie zostanie użyta metoda Maximum Triangle Slope.

Informacje o postępie algorytmu

W trakcie działania skryptu może zdarzyć się, że chcemy wyświetlić dodatkowe informacje o aktualnym postępie pracy. Jest to szczególnie przydatne przy czasochłonnych operacjach. Z pomocą przychodzi moduł progress, który udostępnia metody pozwalające ustawić procentowe zaawansowanie obliczeń lub opis aktualnych działań:

  • progress.setPercentage(i) – pozwala ustawić wartość paska postępu w dolnej części okna, parametr i powinien mieć wartość od 0 do 100;
  • progress.setInfo(tekst, error=False) – wyświetla podany komunikat w oknie Log. Jeśli drugi argument zostanie ustawiony na True to wyświetlony tekst będzie miał kolor czerwony (przydatne przy informowaniu o błędach);
  • progress.setText(tekst) – jw. ale dodatkowo tekst pojawia się nad paskiem postępu;
  • progress.setCommand(tekst) – wyświetla komunikat w oknie Log w formacie tekstu o stałej szerokości znaków;
  • progress.setDebugInfo(tekst) – wyświetla komunikat w oknie Log w kolorze niebieskim;
  • progress.setConsoleInfo(tekst) – jw. ale w kolorze jasnoszarym.

[notice]Funkcje setCommand, setDebugInfo i setConsoleInfo wyświetlą informacje w oknie tylko jeśli w opcjach Geoprocesingu zaznaczona jest opcja Show extra info in Log panel. Są one pomocne głównie przy tworzeniu skryptu, w ostatecznej wersji należy używać setInfo lub setText.[/notice]

Przykładowe użycie powyższych funkcji:

[code lang=”python”]from time import sleep
progress.setInfo(’setInfo(tekst)’)
progress.setInfo(’setInfo(tekst, True)’, True)
progress.setCommand(’setCommand(tekst)’)
progress.setDebugInfo(’setDebugInfo(tekst)’)
progress.setConsoleInfo(’setConsoleInfo(tekst)’)
for i in range(10):
progress.setPercentage(i*10)
progress.setText(’setPercentage: %d’ % (i*10))
sleep(0.5)[/code]

log_window

Przerywanie działania skryptu

Jeżeli po uruchomieniu algorytmu wystąpi krytyczny błąd uniemożliwiający dalsze działanie należy go przerwać. W tym celu można wykorzystać klasę GeoAlgorithmExecutionException, która pozwala przerwać działanie skryptu oraz wyświetlić odpowiedni komunikat:

[code lang=”python”]##dzielnik=number 0
from processing.core.GeoAlgorithmExecutionException import GeoAlgorithmExecutionException
if dzielnik == 0:
raise GeoAlgorithmExecutionException(u’Dzielenie przez zero!’)

[/code]

error_log

Edytor pomocy

help_editor

Edytor pomocy pozwala przygotować opis algorytmu i jego parametrów. Można go wywołać przyciskiem edithelp. W górnej części wyświetlony jest podgląd pomocy. Poniżej, z lewej strony znajduje się lista elementów do edycji. Dostępne pozycje:

  • Algorithm description – ogólny opis skryptu;
  • Input parameters – opis poszczególnych parametrów;
  • Output – opis danych wyjściowych;
  • Algorithm created by – autor skryptu;
  • Algorithm help written by – autor pomocy.

Po wybraniu pozycji w prawej części okna można wpisać treść pomocy dla danego elementu. Pliki pomocy mają taką samą nazwę jak skrypt, ale mają rozszerzenie .help.


Stworzone skrypty widoczne są w oknie Narzędzia geoprocessingu pod pozycją Scripts . Po zapisaniu można je używać jak pozostałe algorytmy lub wykorzystać w graficznym modelarzu lub innym skrypcie.

narzedzia_geoprocessingu_skrypty

Domyślnie przechowywane one są w katalogu konfiguracyjnym QGIS /.qgis2/processing/scripts/. Ścieżkę tą można zmienić w opcjach geoprocesingu. Można je kopiować i przenosić na inne komputery jak zwykłe pliki.

skrypty_pliki

Tagi: ,
Usprawnianie pracy z Konsolą Pythona w Quantum GIS

Dzięki Konsoli Pythona, wbudowanej w Quantum GIS, użytkownik może korzystać z udostępnionego przez tą aplikację API do przeglądania i manipulowania danymi przestrzennymi. Podczas uruchamiania programu automatycznie wczytywane są moduły qgis.core i qgis.utils, dzięki czemu od razu po otworzeniu Konsoli można korzystać z dostępnych w nich klas i funkcji.

Jeśli często korzystamy z konsoli, możemy usprawnić swoją pracę poprzez dostosowanie modułów wczytywanych podczas startu Quantum GIS. Aby tego dokonać należy zmodyfikować plik console.py znajdujący się w katalogu qgis_path\python\qgis, gdzie qgis_path to katalog, w którym został zainstalowany QGIS (np. C:\OSGeo4W\apps\qgis).

[notice]Jeśli używamy wersji rozwojowej master należy zmodyfikować plik console_sci.py znajdujący się w katalogu qgis_path\python\console. Należy pamiętać, że w przypadku aktualizacji oprogramowania, np. instalatorem OSGeo4W, plik ten zostanie nadpisany, a wprowadzone zmiany utracone![/notice]

W powyższym pliku należy znaleźć linię:

[code lang=”python” firstline=”33″]_init_commands = ["from qgis.core import *", "import qgis.utils"][/code]

Zmienna _init_commands to lista zawierająca polecenia, które zostaną wykonane podczas pierwszego uruchamiania Konsoli Pythona podczas danej sesji. Jak widać najpierw wczytywane są wszystkie klasy z moduły qgis.core, a następnie moduł qgis.utils. Dodając nowe pozycje do listy można w prosty sposób dostosować zestaw modułów ładowanych przy starcie QGIS, np. zmieniając linię kodu na:

[code lang=”python” firstline=”33″]_init_commands = ["from qgis.core import *", "import qgis.utils",
"from qgis.utils import iface"][/code]

dostęp do aktualnej instancji klasy QgisInterface będzie znacznie prostszy – wystarczy wpisać iface.activeLayer() aby uzyskać dostęp do aktualnie zaznaczonej warstwy na liście (normalnie należy wpisać qgis.utils.iface.activeLayer()). W ten sposób można załadować dowolne dostępne moduły Pythona jak np. PyQt4 czy math.

_PConsole

Dostęp do instancji klasy QgisInterface przed…

mod_PConsole

…i po wprowadzeniu modyfikacji.

Tagi: ,
„Python Geospatial Development” Erik Westra

Książka opisuje wykorzystanie istniejących rozwiązań Open Source i modułów dostępnych dla języka programowania Python przy tworzeniu aplikacji GIS. Autor prezentuje informacje w formie tutorialu „krok po kroku”. W kolejnych rozdziałach opisane są ogólne metody stosowane w systemach informacji przestrzennej, najważniejsze biblioteki Pythona służące do operacji na danych przestrzennych, korzystanie z baz danych. Praktyczne przykłady pokazują w jaki sposób można samemu stworzyć kompletną aplikację GIS z dostępnych narzędzi Open Source.

Tagi:

GIS SUPPORT sp. z o.o.


SZKOLIMY

z QGIS oraz innego otwartego oprogramowania GIS.

zobacz ofertę szkoleń