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.
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.
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:
Liczby rzeczywiste należy podawać z kropką;
Tak przedstawiają się powyższe kontrolki w oknie skryptu:
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:
[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).
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:
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]
Drugą grupą funkcji pomocniczych są funkcje pozwalające tworzyć nowe warstwy rastrowe, wektorowe i tabele. Znajdują się one w module processing.core.
[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]
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”]>>> processing.alghelp("saga:slopeaspectcurvature")
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 & Burgess 1996)
3 – [3] Fit 2.Degree Polynom (Bauer, Rohdenburg, Bork 1985)
4 – [4] Fit 2.Degree Polynom (Heerdegen & Beran 1982)
5 – [5] Fit 2.Degree Polynom (Zevenbergen & 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("saga:slopeaspectcurvature", raster, 1, nachylenie, …)[/code]
W powyższym przykładzie zostanie użyta metoda Maximum Triangle Slope.
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ń:
[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]
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]
Edytor pomocy pozwala przygotować opis algorytmu i jego parametrów. Można go wywołać przyciskiem . 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:
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.
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.
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.
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.