3. レイヤをロードする

ヒント

このページのコードスニペットは、以下のインポートが必要です:

import os # This is is needed in the pyqgis console also
from qgis.core import (
    QgsVectorLayer
)

データのレイヤを開きましょう。QGISはベクタおよびラスタレイヤを認識できます。加えてカスタムレイヤタイプを利用することもできますが、それについてここでは述べません.

3.1. ベクタレイヤ

ベクタレイヤのインスタンスを作成してプロジェクトに追加するには、レイヤのデータソース識別子、レイヤの名前、プロバイダの名前を指定します:

 1# get the path to the shapefile e.g. /home/project/data/ports.shp
 2path_to_airports_layer = "testdata/airports.shp"
 3
 4# The format is:
 5# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)
 6
 7vlayer = QgsVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
 8if not vlayer.isValid():
 9    print("Layer failed to load!")
10else:
11    QgsProject.instance().addMapLayer(vlayer)

データソース識別子は文字列でそれぞれのベクタデータプロバイダーを表します。レイヤ名はレイヤリストウィジェットの中で使われます。レイヤが正常にロードされたかどうかをチェックすることは重要です。正しくロードされていない場合は不正なレイヤインスタンスが返ります。

geopackageベクタレイヤなら次のようになります:

 1# get the path to a geopackage  e.g. /usr/share/qgis/resources/data/world_map.gpkg
 2path_to_gpkg = os.path.join(QgsApplication.pkgDataPath(), "resources", "data", "world_map.gpkg")
 3# append the layername part
 4gpkg_countries_layer = path_to_gpkg + "|layername=countries"
 5# e.g. gpkg_places_layer = "/usr/share/qgis/resources/data/world_map.gpkg|layername=countries"
 6vlayer = QgsVectorLayer(gpkg_countries_layer, "Countries layer", "ogr")
 7if not vlayer.isValid():
 8    print("Layer failed to load!")
 9else:
10    QgsProject.instance().addMapLayer(vlayer)

QGISでベクタレイヤを開いて表示する最も簡単な方法は、 QgisInterfaceaddVectorLayer() メソッドです:

vlayer = iface.addVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
if not vlayer:
  print("Layer failed to load!")

これは、新しいレイヤを作成し、それを現在の QGIS プロジェクトに追加します(レイヤリストに表示されます)。この関数は、レイヤのインスタンスを返すか、レイヤを読み込むことができなかった場合は None を返します。

以下のリストはベクタデータプロバイダーを使って様々なデータソースにアクセスする方法が記述されています:

  • GDALライブラリ(シェープファイル他多くのファイル形式)--- データソースはファイルへのパスです:

    • シェープファイルの場合:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • dxf(データソースuri中の内部オプションに注意)の場合:

      uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon"
      vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
  • PostGISデータベース - データソースは、PostgreSQLデータベースへの接続を作成するために必要なすべての情報を含む文字列です。

    QgsDataSourceUri クラスを使用すると、この文字列を生成することができます。QGISがPostgresサポートとコンパイルされていない場合、このプロバイダを利用できないことに注意してください:

    1uri = QgsDataSourceUri()
    2# set host name, port, database name, username and password
    3uri.setConnection("localhost", "5432", "dbname", "johny", "xxx")
    4# set database schema, table name, geometry column and optionally
    5# subset (WHERE clause)
    6uri.setDataSource("public", "roads", "the_geom", "cityid = 2643", "primary_key_field")
    7
    8vlayer = QgsVectorLayer(uri.uri(False), "layer name you like", "postgres")
    

    注釈

    uri.uri(False) に渡される False 引数は、認証構成パラメーターの拡張を防ぎます。もし何も認証構成を使用していなければ、この引数は何の違いもありません。

  • CSVなどの区切りテキストファイル --- セミコロンを区切り文字として、X座標をフィールド「x」、Y座標をフィールド「y」としたファイルを開くには、以下のようにします:

    uri = "file://{}/testdata/delimited_xy.csv?delimiter={}&xField={}&yField={}".format(os.getcwd(), ";", "x", "y")
    vlayer = QgsVectorLayer(uri, "layer name you like", "delimitedtext")
    QgsProject.instance().addMapLayer(vlayer)
    

    注釈

    プロバイダーの文字列はURLとして構造化されているので、パスには file:// という接頭辞を付ける必要があります。また、 xy フィールドの代わりにWKT(well-known text)形式のジオメトリを使用でき、座標参照系を指定できます。例えば:

    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    
  • GPXファイル---「GPX」データプロバイダーは、GPXファイルからトラック、ルートやウェイポイントを読み込みます。ファイルを開くには、タイプ(トラック/ルート/ウェイポイント)をURLの一部として指定する必要があります:

    uri = "testdata/layers.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
    QgsProject.instance().addMapLayer(vlayer)
    
  • SpatiaLiteデータベース --- PostGISデータベースと同様に、データソースの識別子を生成するために QgsDataSourceUri を使用することができます:

     1uri = QgsDataSourceUri()
     2uri.setDatabase('/home/martin/test-2.3.sqlite')
     3schema = ''
     4table = 'Towns'
     5geom_column = 'Geometry'
     6uri.setDataSource(schema, table, geom_column)
     7
     8display_name = 'Towns'
     9vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
    10QgsProject.instance().addMapLayer(vlayer)
    
  • MySQL WKBベースのジオメトリ、GDAL経由 --- データソースはテーブルへの接続文字列です:

    uri = "MySQL:dbname,host=localhost,port=3306,user=root,password=xxx|layername=my_table"
    vlayer = QgsVectorLayer( uri, "my table", "ogr" )
    QgsProject.instance().addMapLayer(vlayer)
    
  • WFS 接続: 接続は URI で定義され、 WFS プロバイダを使用します:

    uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
    vlayer = QgsVectorLayer(uri, "my wfs layer", "WFS")
    

    URIは標準の urllib ライブラリを使用して作成できます:

     1import urllib
     2
     3params = {
     4    'service': 'WFS',
     5    'version': '2.0.0',
     6    'request': 'GetFeature',
     7    'typename': 'ms:cities',
     8    'srsname': "EPSG:4326"
     9}
    10uri2 = 'https://demo.mapserver.org/cgi-bin/wfs?' + urllib.parse.unquote(urllib.parse.urlencode(params))
    

注釈

以下の例のように、 QgsVectorLayer インスタンスに対して setDataSource() を呼び出して、既存のレイヤのデータソースを変更することができます:

1uri = "https://demo.mapserver.org/cgi-bin/wfs?service=WFS&version=2.0.0&request=GetFeature&typename=ms:cities"
2provider_options = QgsDataProvider.ProviderOptions()
3# Use project's transform context
4provider_options.transformContext = QgsProject.instance().transformContext()
5vlayer.setDataSource(uri, "layer name you like", "WFS", provider_options)
6
7del(vlayer)

3.2. ラスタレイヤ

ラスタファイルのアクセスには、GDALライブラリを使用します。GDALは様々なファイル形式をサポートしています。一部のファイルを開く際に問題が発生する場合は、使っているGDALが特定のフォーマットをサポートしているかどうかを確認してください(デフォルトですべてのフォーマットが利用可能なわけではありません)。ファイルからラスタを読み込むには、そのファイル名と表示名を指定します:

1# get the path to a tif file  e.g. /home/project/data/srtm.tif
2path_to_tif = "qgis-projects/python_cookbook/data/srtm.tif"
3rlayer = QgsRasterLayer(path_to_tif, "SRTM layer name")
4if not rlayer.isValid():
5    print("Layer failed to load!")

geopackageからラスタを読み込むには:

1# get the path to a geopackage  e.g. /home/project/data/data.gpkg
2path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
3# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
4gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"
5
6rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")
7
8if not rlayer.isValid():
9    print("Layer failed to load!")

ベクタレイヤと同様に、ラスタレイヤは QgisInterface オブジェクトのaddRasterLayer関数を使って読み込むことができます:

iface.addRasterLayer(path_to_tif, "layer name you like")

これは、新しいレイヤを作成し、現在のプロジェクトに追加する(レイヤリストに表示させる)作業を1ステップで行います。

PostGISラスタを読み込むには:

PostGISラスタは、PostGISベクタと同様に、URI文字列を使用してプロジェクトに追加することができます。データベース接続パラメータ用の文字列の再利用可能な辞書を保持することは効率的です。これにより、該当する接続の辞書を簡単に編集することができます。この辞書は、'postgresraster' プロバイダメタデータオブジェクトを使用してURIにエンコードされます。その後、ラスタをプロジェクトに追加することができます。

 1uri_config = {
 2    # database parameters
 3    'dbname':'gis_db',      # The PostgreSQL database to connect to.
 4    'host':'localhost',     # The host IP address or localhost.
 5    'port':'5432',          # The port to connect on.
 6    'sslmode':QgsDataSourceUri.SslDisable, # SslAllow, SslPrefer, SslRequire, SslVerifyCa, SslVerifyFull
 7    # user and password are not needed if stored in the authcfg or service
 8    'authcfg':'QconfigId',  # The QGIS athentication database ID holding connection details.
 9    'service': None,         # The PostgreSQL service to be used for connection to the database.
10    'username':None,        # The PostgreSQL user name.
11    'password':None,        # The PostgreSQL password for the user.
12    # table and raster column details
13    'schema':'public',      # The database schema that the table is located in.
14    'table':'my_rasters',   # The database table to be loaded.
15    'geometrycolumn':'rast',# raster column in PostGIS table
16    'sql':None,             # An SQL WHERE clause. It should be placed at the end of the string.
17    'key':None,             # A key column from the table.
18    'srid':None,            # A string designating the SRID of the coordinate reference system.
19    'estimatedmetadata':'False', # A boolean value telling if the metadata is estimated.
20    'type':None,            # A WKT string designating the WKB Type.
21    'selectatid':None,      # Set to True to disable selection by feature ID.
22    'options':None,         # other PostgreSQL connection options not in this list.
23    'enableTime': None,
24    'temporalDefaultTime': None,
25    'temporalFieldIndex': None,
26    'mode':'2',             # GDAL 'mode' parameter, 2 unions raster tiles, 1 adds tiles separately (may require user input)
27}
28# remove any NULL parameters
29uri_config = {key:val for key, val in uri_config.items() if val is not None}
30# get the metadata for the raster provider and configure the URI
31md = QgsProviderRegistry.instance().providerMetadata('postgresraster')
32uri = QgsDataSourceUri(md.encodeUri(uri_config))
33
34# the raster can then be loaded into the project
35rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")

ラスタレイヤもWCSサービスから作成できます:

layer_name = 'modis'
url = "https://demo.mapserver.org/cgi-bin/wcs?identifier={}".format(layer_name)
rlayer = QgsRasterLayer(uri, 'my wcs layer', 'wcs')

以下は、WCS URIが含むことのできるパラメータの説明です:

WCS URIは & で区切られた key=value のペアで構成されています。URLのクエリ文字列と同じ形式で、同じようにエンコードされます。 QgsDataSourceUri は、特殊文字が適切にエンコードされるようにURIを組み立てるために使用されるべきものです。

  • url (必須): WCSサーバーのURL。WCSの各バージョンでは、GetCapabilities のバージョンに異なるパラメータ名を使用しているため、URLにはVERSIONを使用しないでください(param versionを参照)。

  • identifier (必須): Coverage name

  • time (オプション):時間位置または時間帯 (beginPosition/endPosition[/timeResolution])

  • format (オプション) : サポートされているフォーマット名。デフォルトは名前にtifを伴う最初のサポートされているフォーマット、または最初のサポートされているフォーマット。

  • crs (オプション): AUTHORITY:ID形式によるCRS 例. EPSG:4326。デフォルトはEPSG:4326(サポートされている場合)または最初のサポートされているCRS。

  • username (オプション): 基本認証のUsername。

  • password (オプション): 基本認証のパスワード。

  • IgnoreGetMapUrl (オプション、ハック) : 指定されたとき(1を参照)、GetCapabilitiesが布告したGetCoverage URLを無視する。サーバーが正しく構成されたいないときに必要かもしれない。

  • InvertAxisOrientation (オプション、ハック): 指定されたとき(1 に設定)、GetCoverage 要求で軸を切り替えます。サーバーが間違った軸の順序を使用している場合、地理的なCRSのために必要な場合があります。

  • **IgnoreAxisOrientation**(オプション、ハック): 指定された場合(1 に設定)、地理的 CRS の WCS 標準に従って軸の向きを反転させないようにする。

  • cache (オプション): QNetworkRequest::CacheLoadControl で説明されているように、キャッシュの読み込みを制御します。ただし、AlwaysCache で失敗した場合は PreferCache としてリクエストを再送します。可能な値: AlwaysCache、PreferCache、PreferNetwork、AlwaysNetwork。デフォルトはAlwaysCacheです。

別の方法としては、WMSサーバーからラスターレイヤーを読み込むことができます。しかし現在では、 APIからGetCapabilitiesレスポンスにアクセスすることはできません---どのレイヤが必要か知っている必要があります。

urlWithParams = "crs=EPSG:4326&format=image/png&layers=continents&styles&url=https://demo.mapserver.org/cgi-bin/wms"
rlayer = QgsRasterLayer(urlWithParams, 'some layer name', 'wms')
if not rlayer.isValid():
  print("Layer failed to load!")

3.3. QgsProject インスタンス

開いたレイヤをレンダリングに使用したい場合は、 QgsProject インスタンスに追加することを忘れないようにしてください。QgsProject インスタンスはレイヤの所有権を持ち、後でアプリケーションのどの部分からでも一意のIDによってアクセスすることができます。レイヤがプロジェクトから削除されると、レイヤも削除されます。レイヤはQGISインターフェイスでユーザーが削除することもできますし、Pythonで removeMapLayer() メソッドを使用しても削除できます。

現在のプロジェクトにレイヤを追加するには、 addMapLayer() メソッドを用います:

QgsProject.instance().addMapLayer(rlayer)

絶対位置にレイヤーを追加する:

1# first add the layer without showing it
2QgsProject.instance().addMapLayer(rlayer, False)
3# obtain the layer tree of the top-level group in the project
4layerTree = iface.layerTreeCanvasBridge().rootGroup()
5# the position is a number starting from 0, with -1 an alias for the end
6layerTree.insertChildNode(-1, QgsLayerTreeLayer(rlayer))

レイヤを削除したい場合は、 removeMapLayer() メソッドを使用します:

# QgsProject.instance().removeMapLayer(layer_id)
QgsProject.instance().removeMapLayer(rlayer.id())

上記のコードでは、レイヤのIDを渡していますが(レイヤの id() メソッドで取得できます)、レイヤオブジェクトそのものを渡すことも可能です。

ロードされたレイヤのリストとレイヤIDについては、 mapLayers() メソッドを使用してください:

QgsProject.instance().mapLayers()