3. Katman Yükleme

The code snippets on this page need the following imports:

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

Şimdi veri içeren bazı katmanları açalım. QGIS vektör ve rater tipi katmanları tanır. Ek olarak özel katman tipleri mevcut, fakat bu konudan burada bahsetmeyeceğiz.

3.1. Vektör Katmanları

To create and add a vector layer instance to the project, specify the layer’s data source identifier, name for the layer and provider’s name:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# get the path to the shapefile e.g. /home/project/data/ports.shp
path_to_airports_layer = "testdata/airports.shp"

# The format is:
# vlayer = QgsVectorLayer(data_source, layer_name, provider_name)

vlayer = QgsVectorLayer(path_to_airports_layer, "Airports layer", "ogr")
if not vlayer.isValid():
    print("Layer failed to load!")
else:
    QgsProject.instance().addMapLayer(vlayer)

data_source metin tipindedir ve dosya yolunu gösterir. layer_name katman listesinde gösterim için gerekir. provider_name katman dosyası türüne göre çözümleme sistemini gösterir. isValid() fonksiyonu false döndürürse katman yüklemesinde hata oluşmuş demektir.

Geopackage vektör katmanı için:

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

QGIS içeinde vektör katmanını açıp göstermenin en hızlı yolu QgisInterface: arayüzünün addVectorLayer() metodunu kullanmaktır.

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

Bu kod QGIS projesine sadece bir adımda yeni bir katman ekler (katman listesinde görünür). Fonksiyon bir katman değişkeni döndürür veya katman yüklenemedi ise None döndürür.

Aşağıdaki liste çeşitli vektör veri işleyicilerine nasıl erişebileceğinizi gösteriyor.

  • OGR kütüphanesi (ESRI Shape dosyaları ve birçok diğer format) — veri kaynağı olarak dosya yolu kullanılır:

    • Shape dosyaları için:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • dxf dosyaları (not: ayarlar dosya kaynağı içerisinde):

      uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon"
      vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
  • PostGIS veritabanı - PostgreSQL veritabanı bağlantısı yapmak için gereken bilgilerin olduğu bir bağlantı bilgileri metinidir.

    QgsDataSourceUri sınıfı bağlantı metnini sizin için oluşturur. Not: QGIS, Postgres desteği ile derlenmelidir, diğer türlü sağlayıcı mümkün olamazdı:

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

    Not

    The False argument passed to uri.uri(False) prevents the expansion of the authentication configuration parameters, if you are not using any authentication configuration this argument does not make any difference.

  • CSV or other delimited text files — to open a file with a semicolon as a delimiter, with field “x” for X coordinate and field “y” for Y coordinate you would use something like this:

    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)
    

    Not

    The provider string is structured as a URL, so the path must be prefixed with file://. Also it allows WKT (well known text) formatted geometries as an alternative to x and y fields, and allows the coordinate reference system to be specified. For example:

    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    
  • GPX files — the “gpx” data provider reads tracks, routes and waypoints from gpx files. To open a file, the type (track/route/waypoint) needs to be specified as part of the url:

    uri = "testdata/layers.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
    QgsProject.instance().addMapLayer(vlayer)
    
  • SpatiaLite database — Similarly to PostGIS databases, QgsDataSourceUri can be used for generation of data source identifier:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    uri = QgsDataSourceUri()
    uri.setDatabase('/home/martin/test-2.3.sqlite')
    schema = ''
    table = 'Towns'
    geom_column = 'Geometry'
    uri.setDataSource(schema, table, geom_column)
    
    display_name = 'Towns'
    vlayer = QgsVectorLayer(uri.uri(), display_name, 'spatialite')
    QgsProject.instance().addMapLayer(vlayer)
    
  • MySQL WKB-based geometries, through OGR — data source is the connection string to the table:

    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 connection: the connection is defined with a URI and using the WFS provider:

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

    The uri can be created using the standard urllib library:

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

Not

You can change the data source of an existing layer by calling setDataSource() on a QgsVectorLayer instance, as in the following example:

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

del(vlayer)

3.2. Raster Layers

For accessing raster files, GDAL library is used. It supports a wide range of file formats. In case you have troubles with opening some files, check whether your GDAL has support for the particular format (not all formats are available by default). To load a raster from a file, specify its filename and display name:

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

To load a raster from a geopackage:

1
2
3
4
5
6
7
8
9
# get the path to a geopackage  e.g. /home/project/data/data.gpkg
path_to_gpkg = os.path.join(os.getcwd(), "testdata", "sublayers.gpkg")
# gpkg_raster_layer = "GPKG:/home/project/data/data.gpkg:srtm"
gpkg_raster_layer = "GPKG:" + path_to_gpkg + ":srtm"

rlayer = QgsRasterLayer(gpkg_raster_layer, "layer name you like", "gdal")

if not rlayer.isValid():
    print("Layer failed to load!")

Similarly to vector layers, raster layers can be loaded using the addRasterLayer function of the QgisInterface object:

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

This creates a new layer and adds it to the current project (making it appear in the layer list) in one step.

To load a PostGIS raster:

PostGIS rasters, similar to PostGIS vectors, can be added to a project using a URI string. It is efficient to keep a reusable dictionary of strings for the database connection parameters. This makes it easy to edit the dictionary for the applicable connection. The dictionary is then encoded into a URI using the ‘postgresraster’ provider metadata object. After that the raster can be added to the project.

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

# the raster can then be loaded into the project
rlayer = iface.addRasterLayer(uri.uri(False), "raster layer name", "postgresraster")

Raster layers can also be created from a WCS service:

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

Here is a description of the parameters that the WCS URI can contain:

WCS URI is composed of key=value pairs separated by &. It is the same format like query string in URL, encoded the same way. QgsDataSourceUri should be used to construct the URI to ensure that special characters are encoded properly.

  • url (required) : WCS Server URL. Do not use VERSION in URL, because each version of WCS is using different parameter name for GetCapabilities version, see param version.

  • identifier (required) : Coverage name

  • time (optional) : time position or time period (beginPosition/endPosition[/timeResolution])

  • format (optional) : Supported format name. Default is the first supported format with tif in name or the first supported format.

  • crs (optional) : CRS in form AUTHORITY:ID, e.g. EPSG:4326. Default is EPSG:4326 if supported or the first supported CRS.

  • username (optional) : Username for basic authentication.

  • password (optional) : Password for basic authentication.

  • IgnoreGetMapUrl (optional, hack) : If specified (set to 1), ignore GetCoverage URL advertised by GetCapabilities. May be necessary if a server is not configured properly.

  • 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.

Alternatively you can load a raster layer from WMS server. However currently it’s not possible to access GetCapabilities response from API — you have to know what layers you want:

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