Example of DOV search methods for groundwater permits (grondwatervergunningen)¶
Mind that the data source of groundwater permits is just a WFS. It can be accessed with simple WFS calls from OWSLib. It is included in the pydov API for ease of access for less experienced users. And to provide a general interface with unit testing to all considered objects.
Use cases explained below¶
Get permits in a bounding box
Get permits in a bounding box based on specific properties
Select permits in a municipality and return depth
Get permits, returning fields not available in the standard output dataframe
Get for a certain permit the measured water quality parameters if available
[36]:
%matplotlib inline
import inspect, sys
import warnings; warnings.simplefilter('ignore')
[37]:
# check pydov path
import pydov
Get information about the datatype ‘GrondwaterVergunning’¶
[38]:
from pydov.search.grondwatervergunning import GrondwaterVergunningSearch
gwv = GrondwaterVergunningSearch()
A description is provided for the ‘Gwvergunningen’ datatype (in Dutch):
[39]:
gwv.get_description()
[39]:
'Vergunningen verleend voor het winnen van grondwater kunnen gevisualiseerd en bevraagd worden in de Databank Ondergrond Vlaanderen. \r\nSinds 1999 zijn vergunningen verleend volgens de VLAREM-wetgeving. Ze zijn ingedeeld in klasse 1, 2 of 3, waarbij er voor klasse 1 en 2 een vergunningsplicht geldt en voor klasse 3 een meldingsplicht. De indelingslijst is terug te vinden in VLAREM I (het winnen van grondwater is opgenomen onder rubriek 53). Oudere aanvragen zijn verleend volgens het Grondwaterdecreet. Deze zijn ingedeeld in categorie A, B en C.'
The different fields that are available for objects of the ‘Gwvergunningen’ datatype can be requested with the get_fields() method:
[40]:
fields = gwv.get_fields()
# print available fields
for f in fields.values():
print(f['name'])
id_vergunning
pkey_installatie
exploitant_naam
inrichtingsnummer
watnr
vergunning
vlaremrubriek
vergund_jaardebiet
vergund_dagdebiet
van_datum_termijn
tot_datum_termijn
aquifer_vergunning
diepte
vergund_aantal_putten
inrichtingsklasse
vergunningverlenende_overheid_VVO
referentie_VVO
nacebelcode
IIOA_CBBnr
IIOA_adres
grondwaterlichaam
actie_waakgebied
x
y
exploitant_adres
cbbnr
kbonr
heffingsnummer
exploitant_namen
eerste_invoer
geom
You can get more information of a field by requesting it from the fields dictionary: * name: name of the field * definition: definition of this field * cost: currently this is either 1 or 10, depending on the datasource of the field. It is an indication of the expected time it will take to retrieve this field in the output dataframe. However, since the data source is currently a WFS, the cost of each field is 1 * notnull: whether the field is mandatory or not * type: datatype of the values of this field
[41]:
fields['actie_waakgebied']
[41]:
{'name': 'actie_waakgebied',
'definition': 'de actie- en waakgebieden afgebakend i.k.v. het gebiedspecifieke beleid zoals vastgesteld in de herstelprogrammas voor grondwaterlichamen in ontoereikende kwantitatieve toestand binnen het Centraal Vlaams Systeem, het Brulandkrijtsysteem en het Sokkelsysteem (2016-2021)',
'type': 'string',
'notnull': False,
'query': True,
'cost': 1}
Example use cases¶
Get permits in a bounding box¶
Get data for all the permits that are geographically located within the bounds of the specified box.
The coordinates are in the Belgian Lambert72 (EPSG:31370) coordinate system and are given in the order of lower left x, lower left y, upper right x, upper right y.
[42]:
from pydov.util.location import Within, Box
df = gwv.search(location=Within(Box(153145, 206930, 163150, 216935)))
df.head()
[000/001] .
[42]:
id_vergunning | pkey_installatie | x | y | diepte | exploitant_naam | watnr | vlaremrubriek | vergund_jaardebiet | vergund_dagdebiet | van_datum_termijn | tot_datum_termijn | aquifer_vergunning | inrichtingsklasse | nacebelcode | actie_waakgebied | cbbnr | kbonr | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 66167 | https://www.dov.vlaanderen.be/data/installatie... | 153698.11 | 213812.68 | 10.0 | HOOYBERGHS | ANT-00586-A | 53.2.2.b)2. | 50000.0 | NaN | 2019-06-07 | 2020-02-07 | 0250: Mioceen Aquifersysteem | Klasse 2 | 41201: Algemene bouw van residentiële gebouwen... | geen actie/waakgebieden | NaN | 0424877618 |
1 | 67692 | https://www.dov.vlaanderen.be/data/installatie... | 154171.79 | 214241.69 | NaN | AQUAFIN | ANT-01287-A | 53.2.2.b)2. | 200000.0 | NaN | 2021-03-08 | 2023-09-08 | 0100: Quartaire aquifersystemen | Klasse 2 | 37: Afvalwaterafvoer | geen actie/waakgebieden | 00418870000022 | 0440691388 |
2 | 68060 | https://www.dov.vlaanderen.be/data/installatie... | 157404.31 | 212039.04 | 10.0 | Strabag Belgium | ANT-01711-A | 53.2.1.b | 1300.0 | NaN | 2020-08-21 | NaN | 0250: Mioceen Aquifersysteem | Klasse 2 | 41203: Algemene bouw van andere niet-residenti... | NaN | NaN | 0472028526 |
3 | 68899 | https://www.dov.vlaanderen.be/data/installatie... | 161741.40 | 216702.31 | 7.0 | Beyers Nancy | ANT-02159-A | 53.2.2.a) | 17640.0 | 360.0 | 2020-12-17 | NaN | 0100: Quartaire aquifersystemen | Klasse 3 | 0000: onbekend | geen actie/waakgebieden | NaN | NaN |
4 | 68967 | https://www.dov.vlaanderen.be/data/installatie... | 159355.06 | 215945.52 | 7.0 | KRUISPAD | ANT-02204-A | 53.2.2.a) | 16757.0 | 140.0 | 2020-12-30 | NaN | 0230: Pleistoceen en Plioceen aquifer | Klasse 3 | 0000: onbekend | NaN | NaN | 0712688197 |
[43]:
len(df)
[43]:
471
471 permits were obtained in this bbox. However, not all permits are stil active, indicated by tot_datum_termijn. For more information about the extracted volumes, referenced by vlaremrubriek, see Vlarem II. See this link for more information about the potential definitions.
[44]:
fields['vlaremrubriek']
[44]:
{'name': 'vlaremrubriek',
'definition': 'Code die gebruikt wordt in VLAREM (bijlage 1 VLAREM II) om een rubriek aan te duiden',
'type': 'string',
'notnull': False,
'query': True,
'cost': 1}
Get permits in a bounding box with specific properties¶
Next to querying permits based on their geographic location within a bounding box, we can also search for permits matching a specific set of properties. For this we can build a query using a combination of the ‘Gwvergunningen’ fields and operators provided by the WFS protocol.
A list of possible operators can be found below:
[45]:
[i for i,j in inspect.getmembers(sys.modules['owslib.fes2'], inspect.isclass) if 'Property' in i]
[45]:
['PropertyIsBetween',
'PropertyIsEqualTo',
'PropertyIsGreaterThan',
'PropertyIsGreaterThanOrEqualTo',
'PropertyIsLessThan',
'PropertyIsLessThanOrEqualTo',
'PropertyIsLike',
'PropertyIsNotEqualTo',
'PropertyIsNull',
'SortProperty']
In this example we build a query using the PropertyIsGreaterThan operator in addition to the earlier bbox, to restrict the query to active permits:
[46]:
from owslib.fes2 import PropertyIsGreaterThan
query = PropertyIsGreaterThan(propertyname='tot_datum_termijn',
literal='2020-09-01')
df = gwv.search(query=query,
location=Within(Box(153145, 206930, 163150, 216935)))
df.head()
[000/001] .
[46]:
id_vergunning | pkey_installatie | x | y | diepte | exploitant_naam | watnr | vlaremrubriek | vergund_jaardebiet | vergund_dagdebiet | van_datum_termijn | tot_datum_termijn | aquifer_vergunning | inrichtingsklasse | nacebelcode | actie_waakgebied | cbbnr | kbonr | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 67692 | https://www.dov.vlaanderen.be/data/installatie... | 154171.79 | 214241.69 | NaN | AQUAFIN | ANT-01287-A | 53.2.2.b)2. | 200000.0 | NaN | 2021-03-08 | 2023-09-08 | 0100: Quartaire aquifersystemen | Klasse 2 | 37: Afvalwaterafvoer | geen actie/waakgebieden | 00418870000022 | 0440691388 |
1 | 75181 | https://www.dov.vlaanderen.be/data/installatie... | 159353.39 | 215831.45 | 8.0 | UP CONSTRUCT | ANT-02817-A | 53.2.2.b)2. | 115000.0 | NaN | 2022-07-06 | 2023-03-21 | 0100: Quartaire aquifersystemen | Klasse 2 | 43390: Overige werkzaamheden in verband met de... | geen actie/waakgebieden | NaN | 0435155559 |
2 | 80487 | https://www.dov.vlaanderen.be/data/installatie... | 155163.90 | 213762.33 | NaN | Beheersmaatschappij Antwerpen Mobiel en Tijdel... | VLA-00642-A | 53.2.2.b)2. | 1075058.0 | 6506.0 | 2023-02-23 | 2024-06-30 | 0250: Mioceen Aquifersysteem | Klasse 1 - Vlaams project | 0000: onbekend | geen actie/waakgebieden | NaN | NaN |
3 | 80490 | https://www.dov.vlaanderen.be/data/installatie... | 155163.90 | 213762.33 | 2.5 | Beheersmaatschappij Antwerpen Mobiel en Tijdel... | VLA-00642-A | 53.11.1 | 1075058.0 | 6506.0 | 2023-02-23 | 2024-06-30 | 0250: Mioceen Aquifersysteem | Klasse 1 - Vlaams project | 0000: onbekend | geen actie/waakgebieden | NaN | NaN |
4 | 81179 | https://www.dov.vlaanderen.be/data/installatie... | 158820.75 | 215899.98 | 7.3 | Algemene Ondernemingen August Van Cauter | 2023069188-A | 53.2.2.a) | 15000.0 | 500.0 | 2023-07-03 | 2023-08-02 | 0100: Quartaire aquifersystemen | Klasse 3 | 41101: Ontwikkeling van residentiële bouwproje... | geen actie/waakgebieden | NaN | 0412137756 |
[47]:
len(df)
[47]:
84
Contrary to the earlier query, this result contains considerably less active permits in the considered bbox.
Mind that among these permits, there could also be permits for dewatering works, or ATES systems. Both of these are mostly not important in the development of a hydrogeological model. For dewatering works, it is currently not possible to see the operational status. These works could have well been finished some time ago, or not. See this link for more information about vlaremrubriek codes.
Select permits in a municipality and return depth¶
We can limit the columns in the output dataframe by specifying the return_fields parameter in our search.
In this example we query all the permits in the city of Ghent and return their depth. For this a remote WFS GML query is used as described in this notebook:
[48]:
from owslib.etree import etree
from owslib.wfs import WebFeatureService
from owslib.fes import PropertyIsEqualTo
from pydov.util.location import GmlFilter
gemeentegrenzen = WebFeatureService(
'https://geo.api.vlaanderen.be/VRBG/wfs',
version='1.1.0')
naam_filter = PropertyIsEqualTo(propertyname='NAAM', literal='Gent')
gemeente_poly = gemeentegrenzen.getfeature(
typename='VRBG:Refgem',
filter=etree.tostring(naam_filter.toXML()).decode("utf8"),
outputFormat='text/xml; subtype=gml/3.2').read()
df = gwv.search(
location=GmlFilter(gemeente_poly, Within),
return_fields=('id_vergunning', 'diepte'))
df.hist(column='diepte')
[000/001] .
[48]:
array([[<Axes: title={'center': 'diepte'}>]], dtype=object)
[49]:
df.describe()
[49]:
diepte | |
---|---|
count | 1461.000000 |
mean | 19.852656 |
std | 31.676266 |
min | -1.000000 |
25% | 5.000000 |
50% | 7.500000 |
75% | 21.000000 |
max | 385.000000 |
Get permit data, returning fields not available in the standard output dataframe¶
Not all fields are available in the default output frame. However, you can examine the available fields with the get_fields() method and pass the desired field name to the return_fields parameter.
[50]:
from owslib.fes2 import PropertyIsGreaterThanOrEqualTo
query = PropertyIsGreaterThanOrEqualTo(
propertyname='diepte',
literal='200')
df = gwv.search(
location=GmlFilter(gemeente_poly, Within),
return_fields=('id_vergunning', 'diepte', 'vergunningverlenende_overheid_VVO'))
df.head()
[000/001] .
[50]:
id_vergunning | diepte | vergunningverlenende_overheid_VVO | |
---|---|---|---|
0 | 60451 | 60.0 | Provinciebestuur OOST-VLAANDEREN |
1 | 66888 | 5.0 | Gemeentebestuur GENT |
2 | 66889 | 5.0 | Gemeentebestuur GENT |
3 | 66992 | 4.0 | Gemeentebestuur GENT |
4 | 67238 | 3.0 | Gemeentebestuur GENT |
Estimate groundwater quality data for a certain permit¶
[51]:
from pydov.util.location import Within, Box
from owslib.fes2 import PropertyIsEqualTo
import pandas as pd
query = PropertyIsEqualTo(propertyname='inrichtingsnummer',
literal='20181004-0018')
df_permit = gwv.search(query=query)
df_permit.head()
[000/001] .
[51]:
id_vergunning | pkey_installatie | x | y | diepte | exploitant_naam | watnr | vlaremrubriek | vergund_jaardebiet | vergund_dagdebiet | van_datum_termijn | tot_datum_termijn | aquifer_vergunning | inrichtingsklasse | nacebelcode | actie_waakgebied | cbbnr | kbonr | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 64279 | https://www.dov.vlaanderen.be/data/installatie... | 174097.89 | 174672.54 | 11.0 | Rialto Holding | VLB-00133-A | 53.2.2.a) | 22450.0 | 445.0 | 2019-05-29 | 2023-03-16 | 0620: Zand van Brussel | Klasse 3 | 64200: Holdings | NaN | NaN | 0675544028 |
[52]:
from pydov.search.grondwaterfilter import GrondwaterFilterSearch
from pydov.search.grondwatermonster import GrondwaterMonsterSearch
from pydov.util.query import Join
gfs = GrondwaterFilterSearch()
fields = gfs.get_fields()
# print available fields
for f in fields.values():
print(f['name'])
gw_id
pkey_grondwaterlocatie
filternummer
pkey_filter
namen
filtergrafiek
putgrafiek
aquifer
diepte_onderkant_filter
lengte_filter
putsoort
filtertype
meetnet
x
y
start_grondwaterlocatie_mtaw
gemeente
grondwaterlichaam
afgesloten_volgens_gwdecreet
datum_in_filter
datum_uit_filter
stijghoogterapport
analyserapport
boornummer
boringfiche
peilmetingen_van
peilmetingen_tot
kwaliteitsmetingen_van
kwaliteitsmetingen_tot
recentste_exploitant
beheerder
eerste_invoer
recentste_installatie
geom
meetnet_code
aquifer_code
grondwaterlichaam_code
regime
datum
tijdstip
peil_mtaw
betrouwbaarheid
methode
filterstatus
filtertoestand
mv_mtaw
[53]:
from pydov.search.grondwaterfilter import GrondwaterFilterSearch
from pydov.search.grondwatermonster import GrondwaterMonsterSearch
from pydov.util.query import Join
gfs = GrondwaterFilterSearch()
gwmonster = GrondwaterMonsterSearch()
df_gfs = gfs.search(location=Within(Box(170000, 174000, 190000, 180000)),
return_fields=['pkey_filter', 'x', 'y', 'aquifer', 'diepte_onderkant_filter'])
filters = df_gfs[(df_gfs['aquifer'].str.contains('0620')) ]
filters.head()
[000/001] .
[53]:
pkey_filter | x | y | aquifer | diepte_onderkant_filter | |
---|---|---|---|---|---|
26 | https://www.dov.vlaanderen.be/data/filter/2021... | 173724.0 | 175112.0 | 0620 - Zand van Brussel | 19.0 |
27 | https://www.dov.vlaanderen.be/data/filter/2021... | 173727.0 | 175127.0 | 0620 - Zand van Brussel | 19.0 |
28 | https://www.dov.vlaanderen.be/data/filter/2021... | 173755.0 | 175104.0 | 0620 - Zand van Brussel | 19.0 |
29 | https://www.dov.vlaanderen.be/data/filter/2021... | 173769.0 | 175122.0 | 0620 - Zand van Brussel | 19.0 |
30 | https://www.dov.vlaanderen.be/data/filter/2021... | 173798.0 | 175119.0 | 0620 - Zand van Brussel | 19.0 |
Now select the according water quality data
[54]:
df_gwq = gwmonster.search(query=Join(filters, 'pkey_filter'),
)
df_gwq['parameter'] = df_gwq['parameter'].str.encode('utf-8')
df_gwq['parameter'].unique()
[000/001] .
[000/210] cccccccccccccccccccccccccccccccccccccccccccccccccc
[050/210] cccccccccccccccccccccccccccccccccccccccccccccccccc
[100/210] cccccccccccccccccccccccccccccccccccccccccccccccccc
[150/210] cccccccccccccccccccccccccccccccccccccccccccccccccc
[200/210] cccccccccc
[54]:
array([b'Na', b'EC', b'Mg', b'Cd', b'Ca', b'NO2', b'Zn', b'Al', b'CN',
b'Cr', b'K', b'HCO3', b'F', b'Cl', b'As', b'Cu', b'T', b'Ni',
b'Pb', b'NH4', b'TOC', b'Mn', b'NO3', b'CO3', b'Fe', b'O2',
b'Eh\xc2\xb0', b'PO4', b'Fe2+', b'SO4', b'Hg', b'pH', b'EC(Lab.)',
b'Co', b'pH(Lab.)', b'Isoprot', b'chazr', b'Bentaz', b'metola-S',
b'atr_des', b'Terbu', b'Diur', b'Simaz', b'VIS', b'DMS',
b'Chlortol', b'BAM', b'Atraz', b'AMPA', b'Chloridaz', b'Glyfos',
b'Linur', b'SomAN', b'SomKAT', b'B', b'%AfwijkBalans',
b'trichlorpyr', b'Mesotri', b'fluopicolide', b'meta9', b'Dchdzn',
b'meta4', b'meta11', b'Imida', b'Triflox', b'Metola-S-ESA',
b'flufe', b'meta8', b'Br', b'TDS', b'Temp.', b'PropaCl', b'24d',
b'Linur_mono', b'Propan', b'Terbu_des', b'Carben',
b'Atr_desisoprop', b'Propaz', b'brom', b'Ethofum', b'mcpa',
b'Carbet', b'Cyana', b'Metaza', b'Prometr', b'Clproph',
b'5ClFenol', b'Metox', b'Ala', b'Metobro', b'Metami', b'245t',
b'24db', b'Fenoprop', b'Mecopr', b'Fluroxypyr', b'Terbutryn',
b'mcpb', b'Methabenz', b'Dichlorpr', b'Sebu', b'Hexaz', b'Dicam',
b'Per', b'Tri'], dtype=object)
[55]:
pars_select = [b'Fe', b'Fe2+', b'Fe(Tot.)', b'Fe3+']
df_selected = df_gwq.loc[df_gwq.parameter.isin(pars_select), :]
df_stat = df_selected.loc[:, ['parameter', 'waarde']].groupby('parameter').describe().unstack(1)
df_stat
[55]:
parameter
waarde count b'Fe' 200.000000
b'Fe2+' 75.000000
mean b'Fe' 1.480600
b'Fe2+' 0.701600
std b'Fe' 1.955772
b'Fe2+' 1.268584
min b'Fe' 0.000000
b'Fe2+' 0.000000
25% b'Fe' 0.020000
b'Fe2+' 0.020000
50% b'Fe' 0.300000
b'Fe2+' 0.070000
75% b'Fe' 3.355000
b'Fe2+' 0.650000
max b'Fe' 12.300000
b'Fe2+' 4.400000
dtype: float64
Mind the units of the values.
[56]:
df_selected.eenheid.unique()
[56]:
array(['mg/l'], dtype=object)
As such, the iron content of the considered hydrogeological layer is on average 1.5 mg/L with a stdev of 1.97 mg/L. This is most likely above the standars for use as irrigation water (see this link). Mind that further processing with a limited selection of the two nearest monitoring screens is possible. And even further, an indication of the nearest OVAM sites can be obtaind from the WFS with (in Dutch) ‘Dossierinfo’ as available from this link.