QGIS pythonコンソール使用法など[備忘録]

今回の記事では、QGISでpythonコンソールを扱う方法を記述します。

[背景]
～QGISのpythonコンソールの説明が充実していないため

[対象]
～pythonコンソールにより、マウスをカチカチ動かす単純作業を自動化したい人
～pythonをある程度使ったことのある人でパスなどの概念がわかる人

[本題]
QGISでコンソールを開くには CTRL+Alt+pを押します。下の画像のようなウィンドウがでてきます。
![スクリーンショット 2023-11-11 195711.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/a6f6e7d3-127f-0166-3929-81200b47b451.png)

左上の赤で囲まれている部分が良く使うコマンドです。
〇箒マーク＝コンソール上の出力結果を全て消す
〇再生マーク＝pythonプログラムを実行する
〇メモ帳マーク＝pythonのプログラムファイルを開く。
(QGISでpythonを使う際は、メモ帳マークを使います)

メモ帳マークでプログラムの作成を開始するため、これを押します。
すると以下の画像のようになります。
![スクリーンショット 2023-11-11 200302.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/dd4ac762-2214-e792-beba-f9651389e204.png)

pyファイルが"無題-0"となっております。pyファイルを保存するには、右側の再生マークの左隣にあるディスクマークを押します。
(ctrl + sで保存されるのはQGISプロジェクトです。気をつけて下さい。)

そして、作成したpyファイルを実行するためには右側の再生マークを押します。
右側の再生マークを押すことで、選択されている (目に見えている)pyファイルを実行できます。


①機能の確認

以下のコードで、ユーザーのQGISに実装されている機能を確認します。
```python
import processing
for alg in QgsApplication.processingRegistry().algorithms():
    print(alg.id(), "->", alg.displayName())
```
以下のような出力結果が出ます。

```python
#例
#左側が機能名です (こちらを今後使います)。
#右側がQGISに表示されている普段見るほうの名前です。
gdal:aspect -> 傾斜方位（aspect）
native:addautoincrementalfield -> 自動インクリメント属性を追加
saga:rastercombination -> RasterCombination
.....
```
画像だと、以下のようになります。
![スクリーンショット 2023-11-11 200957.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/4fa3eed8-cd29-e5b4-6aac-8ab91946027e.png)

②特定の機能の入力を確認
続いて、使いたい機能を実行するために必要な"入力すべきもの"を確認します。
以下のプログラムを使用します。
```python
import processing
#例
#name=gdal:aspect
#name=native:addautoincrementalfield
name="使いたい機能" 

processing.algorithmHelp(name)
```
試しに、native:clipで実行します。以下のような結果になります。
![スクリーンショット 2023-11-11 201922.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/ffa3b2e1-c19e-171c-41ee-bad6e3ec8fe5.png)

左側の実行結果の全てを確認します。
```python
>>exec(open('C:/Users/okina/AppData/Local/Temp/tmpc6nko72s.py'.encode('utf-8')).read())
切り抜く（clip） (native:clip)

このアルゴリズムは、別のポリゴンレイヤの地物を使用して入力ベクタレイヤを切り抜きます（クリップします）。オーバーレイレイヤのポリゴンと重なった部分だけが出力レイヤに追加されます。

地物の面積や長さなどのプロパティは、クリッピング（切り抜き）によって変更されますが、地物の属性テーブルは変更されません。そのようなプロパティがテーブルに格納されている場合、手動で更新（再計算）する必要があります。


----------------
Input parameters
----------------

INPUT: 入力レイヤ

	Parameter type:	QgsProcessingParameterFeatureSource

	Accepted data types:
		- str: layer ID
		- str: layer name
		- str：レイヤソース
		- QgsProcessingFeatureSourceDefinition
		- QgsProperty
		- QgsVectorLayer

OVERLAY: オーバーレイレイヤ

	Parameter type:	QgsProcessingParameterFeatureSource

	Accepted data types:
		- str: layer ID
		- str: layer name
		- str：レイヤソース
		- QgsProcessingFeatureSourceDefinition
		- QgsProperty
		- QgsVectorLayer

OUTPUT: 切り抜き結果

	Parameter type:	QgsProcessingParameterFeatureSink

	Accepted data types:
		- str：目的のベクタファイル（例： 'd：/test.shp'）
		- str：結果を一時記憶層に格納するための 'memory：'
		- str: プロバイダID接頭辞と目的URI, 例）PostGISのテーブルに結果を保存する場合は'posgres'
		- QgsProcessingOutputLayerDefinition
		- QgsProperty

----------------
Outputs
----------------

OUTPUT:  <QgsProcessingOutputVectorLayer>
	切り抜き結果
```
これは、QGISの上の「ベクター」→「空間演算ツール」→「clip」をpython上で使用するために必要な入力データを示しています。
(ほぼ、関数と同じですね)
GUI上にInput parametersの各要素を重ねると以下のようになります。
![a.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/59d4ca17-ad4a-4e63-8d92-6d63622c3e69.png)

pythonの方の順番とGUIの順番は同じです。
そして、使うべきデータも一緒なので迷うことはないと思います。
INPUT、OVERLAY、OUTPUTにはshapeファイルやjsonファイルなどの地物を入力します。

③実行の仕方
では、どのように実行するかを説明します。
以下のコードがデフォルトです。

```python
import processing
processing.run("native:clip",{
"INPUT":"C:Users/../../yourfile.shp",
"OVERLAY":"C:Users/../../yourfile.shp",
"OUTPUT":"C:Users/../../output_file_name.shp"
})
```

これをpythonファイルに打ち込んで、各項目を定義して実行すればQGISの機能がpythonで使用できます。
単体で使うならこれでいいですが、pythonで実行する最大のメリットは、"他の機能を組み合わせて一気に処理できる"ことにあります。

ルーティンのような処理を毎度のごとく、新しいデータに施しても時間が無駄となってしまいます。
または、何百とあるデータに対して一定の処理をかけるのも、GUIでやると苦行です。
効率的に業務を進めるためにも、そういった場合に非常に力を発揮する手段です。

そういうわけで、以下にforループも併せたサンプルコードを記述しておきます。
おまけのようなものなので、参考までに活用してください。

```python
import os
import processing

def clipping(input,overlay,output):
    processing.run("native:clip",{
    "INPUT":input,
    "OVERLAY":overlay,
    "OUTPUT":output
    })

#フィールド計算機によるポリゴン面積の計算
def area_cal(input,output):
    result=processing.run("native:fieldcalculator",{
    "INPUT":input,
    "FIELD_NAME":"Area",#結果を保存したいフィールド名
    "FIELD_TYPE":1,#1は整数、0は小数点
    "FIELD_LENGTH":5,#フィールド計算機でいう精度
    "FOURMULA":"$area",#フィールド計算機で入力している式 (""と''を分けて使用すれば幅広く処理できる)
    "OUTPUT":output
    })
    return

input="C:../../file.shp" #inputに使うデータ
overlay_path="C:../.." #overlayしたいデータが入っているフォルダのパス
output_path="C:../.." #結果を保存したいところのファイル
files=os.listdirs(overlay_path)
for f in files:
    if f.endswith(".shp"):#拡張子が.shpのファイル名だけを使用する
        name=f.split(".")[0]#後で使うので、ファイルの名前だけを取り出す
        clipping(input,overlay_path+name+".shp",output_path+name+".shp")
        area_calc(output_path+name+".shp",output_path+name+"_area_calced.shp")
        
```

④おまけ～QGISのpythonに新しいライブラリを実装する
python in QGISには基本的なライブラリは入っています (pandas, numpy, osなど)。
しかし、空間情報を扱えるgeopandasやrasterstats、shapelyなどは入っていません。そういった追加機能的なライブラリの入れ方について簡単に残しておきます。

QGISのショートカットが含まれているフォルダ内にある「OSGeo4W Shell」を使います。
![スクリーンショット 2023-11-11 204956.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/0766604c-5d9a-3a4a-9c5e-1829c0bc9252.png)
これを起動すると、コマンドプロンプトみたいなものが出てきます (コマンドプロンプトそのものですが)。
![スクリーンショット 2023-11-11 205105.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/dcbc9594-dae7-8ec8-5c19-95d18cdcfd57.png)
後は、ここにいつも通りに「pip install ○○」と入力するだけです。
![スクリーンショット 2023-11-11 205249.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1299297/97487828-2933-ead4-19dd-94ab295cdf19.png)

⑤おわりに
ここまで、python in QGISについて概説してきました。基本的な使い方はこれまでです。後は各人のアイディアで次第で、すごいものができると思います。
pythonを使って、自作のプラグインも作れるらしいので、それについてもマスターしたら記録していきたいです。
以上