3. Lagen laden

Hint

De codesnippers op deze pagina hebben de volgende import nodig:

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

Laten we enkele lagen met gegevens openen. QGIS herkent vector- en rasterlagen. Aanvullend zijn aangepaste typen lagen beschikbaar, maar die zullen we hier niet bespreken.

3.1. Vectorlagen

Specificeer de identificatie van de gegevensbron van de laag, de naam voor de laag en de naam van de provider om een instance voor een vectorlaag voor het project te maken of toe te voegen:

 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)

De identificatie van de gegevensbron van de laag is een string en is specifiek voor elke vector gegevensprovider. De naam van de laag wordt gebruikt in de widget Lagenlijst. Het is belangrijk om te controleren of de laag met succes is geladen. Als dat niet zo was wordt een ongeldige instance van de laag teruggegeven.

Voor een laag van 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)

De snelste manier om een vectorlaag te openen en weer te geven in QGIS is de addVectorLayer() van QgisInterface:

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

Dit maakt een nieuwe laag en voegt die toe aan het huidige project van QGIS (waardoor het verschijnt in de lagenlijst). De functie geeft de instance van de laag terug of None als de laag niet kon worden geladen.

De volgende lijst geeft weer hoe toegang wordt verkregen tot verscheidene gegevensbronnen met behulp van vector gegevensproviders:

  • bibliotheek OGR (Shapefiles en vele andere bestandsindelingen) — gegevensbron is het pad naar het bestand:

    • vpor Shapefile:

      vlayer = QgsVectorLayer("testdata/airports.shp", "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
    • voor DXF (let op de interne opties in de URI van de gegevensbron):

      uri = "testdata/sample.dxf|layername=entities|geometrytype=Polygon"
      vlayer = QgsVectorLayer(uri, "layer_name_you_like", "ogr")
      QgsProject.instance().addMapLayer(vlayer)
      
  • database PostGIS - gegevensbron is een tekenreeks met alle benodigde informatie om een verbinding naar een database van PostgreSQL te maken.

    De klasse QgsDataSourceUri kan deze string voor u maken. Onthoud dat QGIS moet worden gecompileerd met ondersteuning voor Postgres, anders is deze provider niet beschikbaar:

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

    Notitie

    Het argument False, doorgegeven aan uri.uri(False), voorkomt het uitbreiden van de parameters voor de configuratie voor authenticatie, indien u geen configuratie voor authenticatie gebruikt maakt dit argument geen enkel verschil.

  • CSV of andere gescheiden tekstbestanden — om een bestand te openen met een punt-komma als scheidingsteken, met veld “x” voor de X-coördinaat en veld “y” voor de Y-coördinaat zou u zoiets als dit gebruiken:

    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)
    

    Notitie

    De string voor de provider is gestructureerd als een URL, dus moet het pad worden voorafgegaan door file://. Ook staat het als WKT (well known text) opgemaakte geometrieën toe als een alternatief voor velden “X” en “Y”, en staat het toe dat het coördinaten referentiesysteem wordt gespecificeerd. Bijvoorbeeld

    uri = "file:///some/path/file.csv?delimiter={}&crs=epsg:4723&wktField={}".format(";", "shape")
    
  • GPX-bestanden — de “GPX”-gegevensprovider leest tracks, routes en waypoints uit GPX-bestanden. Het type (track/route/waypoint) moet worden gespecificeerd als deel van de URL om een bestand te openen:

    uri = "testdata/layers.gpx?type=track"
    vlayer = QgsVectorLayer(uri, "layer name you like", "gpx")
    QgsProject.instance().addMapLayer(vlayer)
    
  • database SpatiaLite — Soortgelijk aan databases van PostGIS, QgsDataSourceUri kan worden gebruikt voor het maken van de identificatie van de gegevensbron:

     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 op WKB gebaseerde geometrieën, via OGR — gegevensbron is de string voor de verbinding naar de tabel:

    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-verbinding: de verbinding wordt gedefinieerd met een URI en het gebruiken van de provider 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")
    

    De URI kan worden gemaakt met behulp van de standaard bibliotheek 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))
    

Notitie

U kunt de databron van een bestaande laag wijzigen door setDataSource() aan te roepen op een instantie van QgsVectorLayer, zoals in het volgende voorbeeld:

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

Voor toegang tot rasterbestanden wordt de bibliotheek GDAL gebruikt. Het ondersteunt een breed scala aan bestandsindelingen. In het geval u problemen hebt met het openen van enkele bestanden, controleer dan of uw GDAL ondersteuning heeft voor die bepaalde indeling (niet alle indelingen zijn standaard beschikbaar). Specificeer zijn bestandsnaam en weergavenaam om een raster uit een bestand te laden:

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

Raster laden vanuit een 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!")

Soortgelijk aan vectorlagen kunnen rasterlagen worden geladen met de functie addRasterLayer van het object QgisInterface:

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

Dit maakt een nieuwe laag en voegt die in één stap toe aan het huidige project (waardoor het verschijnt in de lagenlijst).

Een raster van PostGIS laden:

Rasters van PostGIS kunnen, soortgelijk aan vectors van PostGIS, aan een project worden toegevoegd met een tekenreeks URI. Het is efficiënt om een opnieuw te gebruiken woordenboek van tekenreeksen te maken voor de parameters van de verbinding voor de database. Dit maakt het eenvoudiger het woorden boek te bewerken voor de van toepassing zijnde verbinding. Het woordenboek wordt dan gecodeerd in een lege URI, met het provider metadata object ‘postgresraster’. Daarna kan het raster worden toegevoegd aan het project.

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

Rasterlagen kunnen ook worden gemaakt vanuit een service voor WCS:

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

Hier is een beschrijving van de parameters die de URI voor WCS mag bevatten:

De URI voor WCS is samengesteld uit paren sleutel=waarde, gescheiden door &. Het is dezelfde indeling als een tekenreeks voor een query in een URL, op dezelfde manier gecodeerd. QgsDataSourceUri zou moeten worden gebruikt om de URI te construeren om er voor te zorgen dat speciale tekens op de juiste manier worden gecodeerd.

  • url (vereist) : WCS Server URL. Gebruik geen VERSION in URL, omdat elke versie van WCS een andere naam voor de parameter voor de versie GetCapabilities gebruikt, zie param versie.

  • identifier (vereist) : Bedekkingsnaam

  • time (optioneel) : tijdspositie of tijdsperiode (beginPosition/endPosition[/timeResolution])

  • format (optioneel) : Ondersteunde naam voor indeling. Standaard is de eerste ondersteunde indeling met tif in de naam of de eerste ondersteunde indeling.

  • crs (optioneel) : CRS in de vorm AUTHORITY:ID, bijv. EPSG:4326. Standaard is EPSG:4326 indien ondersteund of het eerste ondersteunde CRS.

  • username (optioneel) : Gebruikersnaam voor basisauthenticatie.

  • password (optioneel) : Wachtwoord voor basisauthenticatie.

  • IgnoreGetMapUrl (optioneel, hack) : Indien gespecificeerd (ingesteld op 1), negeer GetCoverage URL aangeboden door GetCapabilities. Kan nodig zijn als een server niet juist is geconfigureerd.

  • InvertAxisOrientation (optioneel, hack) : Indien gespecificeerd (ingesteld op 1), schakel de as in het verzoek GetCoverage. Kan nodig zijn voor geografisch CRS als een server de verkeerde volgorde voor assen gebruikt.

  • IgnoreAxisOrientation (optioneel, hack) : Indien gespecificeerd (ingesteld op 1), as-oriëntatie niet omdraaien overeenkomstig de standaard van WCS voor geografisch CRS.

  • cache (optioneel) : cache laadbeheer, zoals beschreven in QNetworkRequest::CacheLoadControl, maar verzoek wordt opnieuw verzonden als PreferCache indien mislukt met AlwaysCache. Toegestane waarden: AlwaysCache, PreferCache, PreferNetwork, AlwaysNetwork. Standaard is AlwaysCache.

Als alternatief kunt u een rasterlaag laden vanaf een server voor WMS. Momenteel is het echter niet mogelijk om toegang te krijgen tot het antwoord van GetCapabilities van de API — u moet weten welke lagen u wilt:

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. Instance QgsProject

Als u de geopende lagen wilt gebruiken voor renderen, vergeet dan niet om ze toe te voegen aan de instance QgsProject. De instance QgsProject wordt eigenaar van de lagen en er kan later toegang toe worden verkregen vanuit elk deel van de toepassing door hun unieke ID. Als de laag wordt verwijderd uit het project, wordt hij ook verwijderd. Lagen kunnen door de gebruiker worden verwijderd in de interface van QGIS interface, of via Python met de methode removeMapLayer().

Toevoegen van een laag aan het huidige project wordt gedaan met de methode addMapLayer():

QgsProject.instance().addMapLayer(rlayer)

Een laag op een absolute positie toevoegen:

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

Als u de laag wilt verwijderen, gebruik dan de methode removeMapLayer():

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

In de bovenstaande code wordt de laag-ID doorgegeven (die kunt u zien door het aanroepen van de methode id() van de laag), maar u kunt ook het object laag zelf doorgeven.

Voor een lijst met geladen lagen en laag-ID’s, gebruik de methode mapLayers():

QgsProject.instance().mapLayers()