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 を返します。

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

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

    • Shapefileの場合:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • dxf (note the internal options in data source 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ベースジオメトリ、OGR経由 --- データソースはテーブルへの接続文字列です:

    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 (optional, hack) : If specified (set to 1), switch axis in GetCoverage request. May be necessary for geographic CRS if a server is using wrong axis order.

  • IgnoreAxisOrientation (optional, hack) : If specified (set to 1), do not invert axis orientation according to WCS standard for geographic CRS.

  • cache (optional) : cache load control, as described in QNetworkRequest::CacheLoadControl, but request is resend as PreferCache if failed with AlwaysCache. Allowed values: AlwaysCache, PreferCache, PreferNetwork, AlwaysNetwork. Default is 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 instance

If you would like to use the opened layers for rendering, do not forget to add them to the QgsProject instance. The QgsProject instance takes ownership of layers and they can be later accessed from any part of the application by their unique ID. When the layer is removed from the project, it gets deleted, too. Layers can be removed by the user in the QGIS interface, or via Python using the removeMapLayer() method.

Adding a layer to the current project is done using the addMapLayer() method:

QgsProject.instance().addMapLayer(rlayer)

To add a layer at an absolute position:

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))

If you want to delete the layer use the removeMapLayer() method:

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

In the above code, the layer id is passed (you can get it calling the id() method of the layer), but you can also pass the layer object itself.

For a list of loaded layers and layer ids, use the mapLayers() method:

QgsProject.instance().mapLayers()