Wat is een peilbesluit?
In een peilbesluit legt het waterschap de waterpeilen vast van een begrensd gebied. Het opstellen van een peilbesluit is een wettelijke verplichting. Ook heeft het waterschap een inspanningsverplichting om het vastgestelde peil te handhaven. Bij het opstellen wordt veel data verzameld als over de fysieke conditie en functionele invulling van het gebied. Daarnaast wordt door de tijd gekeken naar de waterhuishouding zowel boven als onder de grond. Het verzamelen van de gegevens was altijd een tijdintensieve stap in het proces. Vanuit het beeld van de API Economy is deze stap te vereenvoudigen, verbeteren en te versnellen. Hieronder laten we zien hoe je gebruik kan maken van het datawarehouse & analyseplatform Lizard om bijvoorbeeld een peilbesluit op te stellen. Meer informatie over Lizard kunt u vinden op https://lizard.net/.
Polder Zegveld
In deze tutorial wordt het peilbesluit van polder Zegveld doorlopen. Polder Zegveld is een veenweidepolder, gelegen tussen Woerden en de Nieuwkoopse Plassen. Binnen een peilbesluit zijn de volgende sets van datagegegevens van belang:
|
|
import packages:
import pandas as pd
import geopandas as gpd
import requests
from pandas.io.json import json_normalize
import matplotlib.pyplot as plt
import numpy as np
import getpass
from datetime import datetime as dt
Inloggegevens Lizard (hiermee maak je connectie met het datawarehouse Lizard):
username = input("Enter username: ")
password = getpass.getpass("Enter password: ")
json_headers = {
"username": username,
"password": password,
"Content-Type": "application/json",
}
headers = {"username": username,
"password": password}
Stap 1: Meetgegevens Grondwater (vanuit het grondwaterbeheersysteem FEWS Vitens)
We kunnen voor de polder Zegveld alle grondwaterstations ophalen mbv de API. We krijgen dan een tabel (Pandas dataframe) terug met alle grondwaterstations. Elk grondwaterstation kan meerdere filters bevatten.
#coordinaten van shapefile polder Zegveld ophalen
boundaries_polder= gpd.read_file('polder_zegveld_bbox.shp')
#api request om grondwaterstations binnen een bepaalde shapefile op te halen
url= 'https://nens.lizard.net/api/v3/groundwaterstations/?in_bbox=4.80209, 52.09391, 4.87680, 52.13360'
r =requests.get(url=url)
df = pd.DataFrame(r.json())
new_df = pd.json_normalize(df['results'])
new_df
Laten we een willekeurig grondwaterstation kiezen die actief is (Peilbuis B31D1423) en daar de freatische filter van selecteren (B31D1423-01). In het datawarehouse Lizard ziet de tijdserie er als volgt uit. We kunnen nu mbv de api de bijbehorende tijdserie ophalen en bewerkingen uitvoeren in deze tijdserie:
|
Laten we beginnen met het ophalen van de data van het jaar 2018:
uuid = '8301e5fe-df88-4816-bfc5-fe8191eeef43' #elke tijdserie heeft een unieke uuid
params= {'start':'2018-01-01T00:00:00Z', 'end':'2019-01-01T00:00:00Z', 'fields':'value'}
url = 'https://nens.lizard.net/api/v3/timeseries/'+uuid+'/data/'
r =requests.get(url=url, params=params)
df_grondwaterstanden = pd.DataFrame(r.json())
df_grondwaterstanden['timestamp'] = pd.to_datetime(df_grondwaterstanden['timestamp'], unit='ms')
df_grondwaterstanden.rename(columns={'timestamp':'Date'}, inplace=True)
df_grondwaterstanden.set_index('Date', inplace=True)
df_grondwaterstanden #we krijgen een pandas dataframe terug met de dagelijks gemeten grondwaterstand waarden
#bereken en plot statistieken in dezelfde plot
#gemiddelde grondwaterstand over deze periode
df_grondwaterstanden['mean'] = df_grondwaterstanden.mean()['value']
#minimale grondwaterstand over deze periode
df_grondwaterstanden['min'] = df_grondwaterstanden.min()['value']
#maximale grondwaterstand over deze periode
df_grondwaterstanden['max'] = df_grondwaterstanden.max()['value']
#mediaan grondwaterstand over deze periode
df_grondwaterstanden['mediaan'] = df_grondwaterstanden.median()['value']
plt.style.use('seaborn')
df_grondwaterstanden.plot(figsize=(20,7))
plt.legend(fontsize='x-large')
We kunnen via de api heel makkelijk en snel tijdseries ophalen binnen een bepaalde tijdsperiode. Dit is gedefinieerd in de api requests beneden bij "params". Ook kunnen we ervoor kiezen om niet de dagelijkse waarde terug te krijgen met de api request, maar de minimale waarde per week (fields & window waarde in de gedefinieerde params).
Verander de "params" zodat alleen de minimale waarde per week van het jaar 2017 wordt gehaald:
uuid = '8301e5fe-df88-4816-bfc5-fe8191eeef43'
params= {'start':'2017-01-01T00:00:00Z', 'end':'2018-01-01T00:00:00Z', 'fields':'min', 'window':'week'}
url = 'https://nens.lizard.net/api/v3/timeseries/'+uuid+'/data/'
r =requests.get(url=url, params=params)
df_grondwaterstanden = pd.DataFrame(r.json())
df_grondwaterstanden['timestamp'] = pd.to_datetime(df_grondwaterstanden['timestamp'], unit='ms')
df_grondwaterstanden.rename(columns={'timestamp':'Date'}, inplace=True)
df_grondwaterstanden.set_index('Date', inplace=True)
df_grondwaterstanden;
df_grondwaterstanden[0:5] # hier krijgen we een pandas dataframe terug met de minimale grondwaterstand per week voor het jaar 2017
Andere gegevens die kunnen worden opgehaald mbv de api zijn de ghg en glg van het grondwaterstation, die in de metadata zijn opgeslagen in het datawarehouse. Ook deze kunnen bevraagd worden met de api. Je vindt een overzicht van de query parameters hier: https://nens.lizard.net/api/v3/timeseries/
Stap 2: Meetgegevens oppervlaktewater (vanuit het waterinformatiesysteem FEWS HDSR)
Voor de polder Zegveld is een peilbesluit genomen met de volgende waarden voor winter en zomerpeil:
|
|
We kunnen vervolgens voor het hydrolisch jaar 2019 onderzoeken wat de peilafwijking is geweest voor de zomer bij een specifiek oppervlaktewater meetstation. We kiezen hiervoor meetstation Molenweg waarvan de locatie is aangegeven in bovenstaande afbeelding.
We halen eerste de data op van dit meetstation van 21 juni 2019 t/m 22 september mbv de api:
#api request om oppervlaktewaterstanden van meetstation Molenweg op te halen:
uuid = '57b8a30d-ff4b-4944-b4ec-23f2e37b21d5'
params= {'start':'2019-06-21T00:00:00Z', 'end':'2019-09-23T00:00:00Z', 'fields':'value'}
url = 'https://nens.lizard.net/api/v3/timeseries/'+uuid+'/data/'
r =requests.get(url=url, params=params)
df_oppervlaktewaterstanden = pd.DataFrame(r.json())
df_oppervlaktewaterstanden['timestamp'] = pd.to_datetime(df_oppervlaktewaterstanden['timestamp'], unit='ms')
df_oppervlaktewaterstanden.rename(columns={'timestamp':'Date'}, inplace=True)
df_oppervlaktewaterstanden.set_index('Date', inplace=True)
df_oppervlaktewaterstanden # we krijgen een pandas dataframe terug met de oppervlaktewaterstanden van meetstation Molenweg,
# dit zijn kwartierwaarden
We plotten nu eerst in 1 grafiek het verloop van de oppervlaktewaterstand en het bijbehorende zomerpeil:
df_oppervlaktewaterstanden['zomerpeil'] = -2.33
df_oppervlaktewaterstanden.plot(figsize=(20,7))
plt.legend(fontsize='x-large')
plt.xlabel('')
plt.ylabel('Oppervlaktewater stand [m NAP]', fontsize=20)
plt.yticks(fontsize=15)
plt.title('kwartierwaarden oppervlaktewater stand tijdens zomer 2019 - meetstation Molenweg', fontsize=20);
We kunnen vervolgens ook de absolute peilafwijking tijdens deze zomer berekenen en plotten in een grafiek:
df_oppervlaktewaterstanden['peilafwijking'] = abs(df_oppervlaktewaterstanden['value'] - df_oppervlaktewaterstanden['zomerpeil'])
df_oppervlaktewaterstanden['peilafwijking'].plot(figsize=(20,7))
plt.legend('')
plt.xlabel('')
plt.ylabel('Peilafwijking [m NAP]', fontsize=20)
plt.xticks(fontsize=15)
plt.yticks(fontsize=15)
plt.title('Peilafwijking tijdens zomerpeil 2019 - meetstation Molenweg', fontsize=20);
Dit kunnen we ook plotten voor het hydrolische jaar 2020 tot nu toe. En we gaan dit keer een temporele aggregatie uitvoeren in de api request, namelijk: de gemiddelde waarde per dag. Verander hiervoor de params waarde en plot de grafieken opnieuw.
#api request om oppervlaktewaterstanden van meetstation Molenweg op te halen voor :
uuid = '57b8a30d-ff4b-4944-b4ec-23f2e37b21d5'
params= {'start':'2020-04-01T00:00:00Z', 'end':'2020-06-23T00:00:00Z', 'fields':'avg', 'window':'day'} #verander hier de query parameters
url = 'https://nens.lizard.net/api/v3/timeseries/'+uuid+'/data/'
r =requests.get(url=url, params=params)
df_oppervlaktewaterstanden = pd.DataFrame(r.json())
df_oppervlaktewaterstanden['timestamp'] = pd.to_datetime(df_oppervlaktewaterstanden['timestamp'], unit='ms')
df_oppervlaktewaterstanden.rename(columns={'timestamp':'Date'}, inplace=True)
df_oppervlaktewaterstanden.set_index('Date', inplace=True)
df_oppervlaktewaterstanden[0:5] # we krijgen een pandas dataframe terug met de oppervlaktewaterstanden van meetstation Molenweg,
# de kwartierwaarden zijn nu geaggregeerd tot gemiddelde dagwaarden.
df_oppervlaktewaterstanden.plot(figsize=(20,7))
plt.legend('')
plt.xlabel('')
plt.ylabel('Oppervlaktewater stand [m NAP]', fontsize=20)
plt.yticks(fontsize=15)
plt.title('Gemiddelde dagelijkse oppervlaktewater stan - meetstation Molenweg', fontsize=20);
Stap 3: Meetgegevens meteo (KNMI)
Belangrijke gegevens voor een polderpeil zijn de meteo gegevens, zoals neerslag en verdamping. Hiermee kunnen we namelijk het neerslagoverschot voor een bepaalde periode berekenen. Neerslag data is beschikbaar in de vorm van een temporeel raster in het datawarehouse Lizard. Voor de verdamping binnen polder Zegveld kijken we naar het dichtsbijzijnde KNMI meetstation Cabauw.
|
|
Laten we beginnen met ophalen van de neerslag raster data binnen de polder Zegveld vanaf 1 april tot 1 oktober 2019 met behulp van de api. We kiezen hiervoor om de rasterdata binnen de polder te aggregeren tot 1 gemiddelde waarde, en dit doen we per maand. We aggregeren dus ruimtelijk, maar ook temporeel.
wkt = 'POLYGON ((4.804847821873415 52.11667280734238, 4.806713259859531 52.11808327571072, 4.805608147820809 52.11856102711491, 4.819366745114616 52.12916174862249, 4.820391627911995 52.12882844174937, 4.825146482688536 52.13155708895362, 4.836760218799797 52.1320950542045, 4.839831083487208 52.13138455359988, 4.841855268314998 52.13279519337573, 4.844997575437689 52.13266472167823, 4.851613567129445 52.13095545048285, 4.850995342194573 52.13013121164453, 4.855100260574258 52.12826534499285, 4.858115526952704 52.1255730225948, 4.857260037781153 52.12489270966972, 4.857432505687366 52.12358885970951, 4.856966250193945 52.12318812892995, 4.857412305450096 52.12198214729695, 4.855523610331791 52.12072942129434, 4.855459491604404 52.1195211452892, 4.856410703395785 52.11874023894567, 4.857189725526387 52.11758407511068, 4.857006548770007 52.11648398314836, 4.858161027579516 52.11509998252357, 4.860588442243921 52.11558196309642, 4.862378153957152 52.11356052316284, 4.863167486792669 52.11317747763539, 4.862651303280372 52.11034849069802, 4.864831936661076 52.10842539029259, 4.864544590469517 52.1078322025319, 4.866034352158711 52.1062563318614, 4.867314973640948 52.10409968552982, 4.86967559135546 52.10353023647684, 4.865590360499596 52.09723068553979, 4.86211402445756 52.09595894201262, 4.861573683244572 52.09520757940017, 4.852430695728541 52.09876627241331, 4.846469734862426 52.10185569966663, 4.842415244351158 52.10297254568547, 4.837985745856069 52.10266207609867, 4.832555777932917 52.10394128701714, 4.831113012822775 52.10480424504518, 4.829541164175933 52.10500217933986, 4.82775049958501 52.10544065304562, 4.824631499045423 52.10542581163859, 4.825548195162908 52.10741128945562, 4.804847821873415 52.11667280734238))'
uuid = "730d6675-35dd-4a35-aa9b-bfb8155f9ca7"
raster_url = "https://nens.lizard.net/api/v4/rasters/"
get_url = f"{raster_url}{uuid}/zonal/"
r = requests.get(
url=get_url,
headers=headers,
params=
{"geom": wkt,
#ruimtelijk aggregeren: je berekent de gemiddelde waarde over alle pixels van het raster
"zonal_statistic": "mean",
"pixel_size": "100",
"zonal_projection":"EPSG:28992",
#temporeel aggregeren: je berekent de gesommeerde maandelijkse waarde van de neerslag, dus in mm/maand
"start": "2019-04-01T00:0:00",
"stop": "2019-10-01T00:00:00",
"temporal_statistic":"sum",
"frequency":'M'
}
)
neerslag = pd.DataFrame(r.json()['results'], columns=['timestamp', 'value'] )
neerslag['timestamp'] = pd.to_datetime(neerslag['timestamp'], unit='s')
neerslag
We krijgen een dataframe terug waarin per maand de neerslag is geaggregeerd (gemiddelde waarde) binnen de polder Zegveld van 1 april t/m 1 juni.
plt.figure(figsize=(15,4))
plt.style.use('seaborn')
bars = neerslag['timestamp']
y_pos = y_pos = np.arange(len(bars))
plt.bar(y_pos, neerslag['value'], width=0.3, color='#008080')
plt.xticks(y_pos, bars, rotation=30, fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Neerslag [mm/maand]', fontsize=20)
plt.title('Neerslag per maand binnen polder Zegveld', fontsize=20)
plt.show()
Vervolgens halen we van het knmi meetstation Cabauw de verdampingsdata op voor dezelfde periode. We gaan ervan uit dat de verdamping gemeten bij dit station representatief is voor het hele poldergebied. Daarnaast gaan we temporeel aggregeren, zodat we de totale verdamping/maand krijgen.
url = "https://nens.lizard.net/api/v3/timeseries/fb30d529-1bc5-4a18-a02f-a48e0d88aa52/data/"
params= {'start':'2019-04-01T00:0:00Z', 'end':'2019-10-01T00:00:00Z', 'fields':'sum', 'window':'month'}
r =requests.get(url=url, params=params)
df_verdamping = pd.DataFrame(r.json())
df_verdamping['timestamp'] = pd.to_datetime(df_verdamping['timestamp'], unit='ms')
df_verdamping
We krijgen een dataframe terug waarin de verdamping is gesommeerd per maand.
plt.figure(figsize=(15,4))
plt.style.use('seaborn')
bars = df_verdamping['timestamp']
y_pos = y_pos = np.arange(len(bars))
plt.bar(y_pos, df_verdamping['sum'], width=0.3, color='#0E497E')
plt.xticks(y_pos, bars, rotation=30, fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('Verdamping [mm/dag]', fontsize=20)
plt.title('Verdamping per maand binnen polder Zegveld', fontsize=20)
plt.show()
Met de neerslag- en verdampingsgegevens kunnen we vervolgens het neerslagoverschot/tekort bepalen per maand voor de polder Zegveld:
# df neerslag mm/maand
neerslag;
#df verdamping mm/maand
df_verdamping;
#dataframe met neerslagoverschot
df_verschil = pd.DataFrame()
df_verschil['value'] = neerslag['value'] - df_verdamping['sum']
df_verschil['timestamp'] = df_verdamping['timestamp']
plt.figure(figsize=(15,4))
plt.style.use('seaborn')
bars = df_verschil['timestamp']
y_pos = y_pos = np.arange(len(bars))
plt.bar(y_pos, df_verschil['value'], width=0.3, color='darkred')
plt.xticks(y_pos, bars, rotation=30, fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('[mm/maand]', fontsize=20)
plt.title('Neerslag tekort/overschot per maand binnen polder Zegveld', fontsize=20)
plt.axhline(y=0, color='k', linestyle='-')
plt.show()
Stap 4: Meetgegevens landgebruik (combinatie van Basis registraties en TOP10)
Voor de polder Zegveld kunnen via het datawarehouse Lizard ook gegevens worden opgehaald over het landgebruik binnen deze polder. Een voorbeeld van het raster "landgebruik" is gevisualiseerd in onderstaande afbeelding.
|
We kunnen van dit raster ook de bijbehorende informatie ophalen via de api voor een specifiek gebied. Zodoende kunnen we ook de percentages van de verschillende landgebruiken voor de polder Zegveld berekenen. We hebben hiervoor een polygoon nodig met de grenzen van de polder Zegveld. We halen dan alleen de raster data op binnen deze polder.|
# polygoon shapefile boundaries polder zegveld
boundaries = gpd.read_file('boundaries_polder_zegveld.shp')
#in de geometrie van de polygoon zitten RD-coordinaten en die moeten voor de api call worden omgezet naar longitude, latitude
boundaries.crs #hiermee kun je de informatie van de geometrie ophalen
boundaries = boundaries.to_crs("EPSG:4326") # geometrie omzetten naar juiste formaat ('EPSG:4326')
import warnings
warnings.filterwarnings('ignore')
#api request met endpoint counts geeft het aantal pixels per landgebruik type terug binnen een bepaalde geometrie (shapefile polder Zegveld) :
url = 'https://demo.lizard.net/api/v4/rasters/a9017ec7-72c4-4bb5-bf06-a221ec916bc6/counts/?geom=POLYGON%20((4.804847821873415%2052.11667280734238,%204.806713259859531%2052.11808327571072,%204.805608147820809%2052.11856102711491,%204.819366745114616%2052.12916174862249,%204.820391627911995%2052.12882844174937,%204.825146482688536%2052.13155708895362,%204.836760218799797%2052.1320950542045,%204.839831083487208%2052.13138455359988,%204.841855268314998%2052.13279519337573,%204.844997575437689%2052.13266472167823,%204.851613567129445%2052.13095545048285,%204.850995342194573%2052.13013121164453,%204.855100260574258%2052.12826534499285,%204.858115526952704%2052.1255730225948,%204.857260037781153%2052.12489270966972,%204.857432505687366%2052.12358885970951,%204.856966250193945%2052.12318812892995,%204.857412305450096%2052.12198214729695,%204.855523610331791%2052.12072942129434,%204.855459491604404%2052.1195211452892,%204.856410703395785%2052.11874023894567,%204.857189725526387%2052.11758407511068,%204.857006548770007%2052.11648398314836,%204.858161027579516%2052.11509998252357,%204.860588442243921%2052.11558196309642,%204.862378153957152%2052.11356052316284,%204.863167486792669%2052.11317747763539,%204.862651303280372%2052.11034849069802,%204.864831936661076%2052.10842539029259,%204.864544590469517%2052.1078322025319,%204.866034352158711%2052.1062563318614,%204.867314973640948%2052.10409968552982,%204.86967559135546%2052.10353023647684,%204.865590360499596%2052.09723068553979,%204.86211402445756%2052.09595894201262,%204.861573683244572%2052.09520757940017,%204.852430695728541%2052.09876627241331,%204.846469734862426%2052.10185569966663,%204.842415244351158%2052.10297254568547,%204.837985745856069%2052.10266207609867,%204.832555777932917%2052.10394128701714,%204.831113012822775%2052.10480424504518,%204.829541164175933%2052.10500217933986,%204.82775049958501%2052.10544065304562,%204.824631499045423%2052.10542581163859,%204.825548195162908%2052.10741128945562,%204.804847821873415%2052.11667280734238))&style=lc-fun-1801c'
r =requests.get(url=url, headers=headers)
landgebruik = pd.DataFrame(r.json()['results'])
landgebruik
We krijgen een tabel terug met het aantal klassen landgebruik binnen de polder Zegveld. Daarnaast halen we met het "counts" endpoint het aantal pixels per landgebruik klasse op binnen dit gebied. We kunnen nu de percentages berekenen die hierbij horen.
#totaal aantal pixels
np.sum(landgebruik['count']) # 35495 pixels
# voeg een kolom in de dataframe toe met percentage landgebruik
landgebruik['percentage'] = landgebruik['count']/np.sum(landgebruik['count']) * 100
landgebruik
Vervolgens kunnen we dit visualiseren in een barplot:
plt.figure(figsize=(20,7))
plt.style.use('seaborn')
bars = landgebruik['label']
colors = landgebruik['color']
y_pos = y_pos = np.arange(len(bars))
plt.bar(y_pos, landgebruik['percentage'], color=colors)
plt.xticks(y_pos, bars, rotation=30, fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('% landgebruik', fontsize=20)
plt.title('Landgebruik verdeling binnen polder Zegveld', fontsize=20)
plt.show()
Er kan worden geconcludeerd dat polder Zegveld vooral bestaat uit Weidehooi wat betreft landgebruik (75%). Als tweede volgt de klasse binnenwater en als derde woongebied.
De query parameters voor rasterdata vind je hier: https://demo.lizard.net/api/v4/rasters/a9017ec7-72c4-4bb5-bf06-a221ec916bc6/.
Stap 5 Bodemtype (BOFEK2012) & Droogleggingsnorm
Aan de hand van het bodemtype kan de droogleggingsnorm worden bepaald en dus is het bodemtype binnen een polder een belangrijke factor voor een peilbesluit. Elke gebruik heeft zijn eigen wensen voor drooglegging. Zo is voor het gebruik grasland een andere drooglegging gewenst, dan voor gebruik als akkerbouw. In het datawarehouse Lizard hebben we een raster "bodemtype". We kunnen van dit raster ook de bijbehorende informatie ophalen via de api voor een specifiek gebied. Hiermee kunnen we achterhalen wat de droogtelegging moet zijn op elke locatie.
De droogleggingsnorm per bodemtype is als volgt geclassificeerd:
|
|
#api request met endpoint counts geeft het aantal pixels per bodemtype terug binnen een bepaalde geometrie (shapefile polder Zegveld) :
url = 'https://demo.lizard.net/api/v4/rasters/9e3534b7-b5d4-46ab-be35-4a0990379f76/counts/?geom=POLYGON%20((4.804847821873415%2052.11667280734238,%204.806713259859531%2052.11808327571072,%204.805608147820809%2052.11856102711491,%204.819366745114616%2052.12916174862249,%204.820391627911995%2052.12882844174937,%204.825146482688536%2052.13155708895362,%204.836760218799797%2052.1320950542045,%204.839831083487208%2052.13138455359988,%204.841855268314998%2052.13279519337573,%204.844997575437689%2052.13266472167823,%204.851613567129445%2052.13095545048285,%204.850995342194573%2052.13013121164453,%204.855100260574258%2052.12826534499285,%204.858115526952704%2052.1255730225948,%204.857260037781153%2052.12489270966972,%204.857432505687366%2052.12358885970951,%204.856966250193945%2052.12318812892995,%204.857412305450096%2052.12198214729695,%204.855523610331791%2052.12072942129434,%204.855459491604404%2052.1195211452892,%204.856410703395785%2052.11874023894567,%204.857189725526387%2052.11758407511068,%204.857006548770007%2052.11648398314836,%204.858161027579516%2052.11509998252357,%204.860588442243921%2052.11558196309642,%204.862378153957152%2052.11356052316284,%204.863167486792669%2052.11317747763539,%204.862651303280372%2052.11034849069802,%204.864831936661076%2052.10842539029259,%204.864544590469517%2052.1078322025319,%204.866034352158711%2052.1062563318614,%204.867314973640948%2052.10409968552982,%204.86967559135546%2052.10353023647684,%204.865590360499596%2052.09723068553979,%204.86211402445756%2052.09595894201262,%204.861573683244572%2052.09520757940017,%204.852430695728541%2052.09876627241331,%204.846469734862426%2052.10185569966663,%204.842415244351158%2052.10297254568547,%204.837985745856069%2052.10266207609867,%204.832555777932917%2052.10394128701714,%204.831113012822775%2052.10480424504518,%204.829541164175933%2052.10500217933986,%204.82775049958501%2052.10544065304562,%204.824631499045423%2052.10542581163859,%204.825548195162908%2052.10741128945562,%204.804847821873415%2052.11667280734238))&style=pawn'
r =requests.get(url=url, headers=headers)
bodem = pd.DataFrame(r.json()['results'])
# voeg een kolom in de dataframe toe met percentage bodem
bodem['percentage'] = bodem['count']/np.sum(bodem['count']) * 100
bodem
plt.figure(figsize=(20,7))
plt.style.use('seaborn')
bars = bodem['label']
colors = bodem['color']
y_pos = y_pos = np.arange(len(bars))
plt.bar(y_pos, bodem['percentage'], color=colors)
plt.xticks(y_pos, bars, rotation=0, fontsize=15)
plt.yticks(fontsize=15)
plt.ylabel('% bodemtype', fontsize=20)
plt.title('Bodemtype verdeling binnen polder Zegveld', fontsize=20)
plt.show()
We hebben in deze polder vooral te maken met veen: ofwel veraarde bovengrond op diep veen ofwel kleidek op veen, of klei op veen. Dit betekent dat de droogleggingsnorm rond de 50-80 cm moet zijn voor de polder Zegveld.
Stap 6 Hoogteligging (AHN3)
Ook het maaiveld speelt een belangrijke rol voor een peilbesluit van een polder. Er is namelijk een droogtelegginsnorm van toepassing en die hangt af van het winter- en/of zomerpeil. Echter hangt deze ook af van het maaiveld bij de watergang. Drooglegging is namelijk het verschil tussen het maaiveld en het polderpeil. Een hoger maaiveld zorgt voor een grotere droogtelegging. Daarnaast zorg een hoger polderpeil juist voor een lagere drooglegging.
![]() |
In het datawarehouse Lizard hebben we een raster "maaiveld", ook wel DEM genoemd. Deze data komt oorspronkelijk van de AHN3. We kunnen van dit raster ook de bijbehorende informatie ophalen via de api voor een specifiek gebied. Daarnaast kan in Lizard voor een gebied de maaiveldcurve worden geplot. Wat wordt hiermee bedoeld? Hiermee wordt de distributie van de data in het raster voor de polder beschreven. Hiermee krijgen we in een oogopslag te zien wat de verdeling van het maaiveld in het poldergebied is.
|
wkt = 'POLYGON ((4.804847821873415 52.11667280734238, 4.806713259859531 52.11808327571072, 4.805608147820809 52.11856102711491, 4.819366745114616 52.12916174862249, 4.820391627911995 52.12882844174937, 4.825146482688536 52.13155708895362, 4.836760218799797 52.1320950542045, 4.839831083487208 52.13138455359988, 4.841855268314998 52.13279519337573, 4.844997575437689 52.13266472167823, 4.851613567129445 52.13095545048285, 4.850995342194573 52.13013121164453, 4.855100260574258 52.12826534499285, 4.858115526952704 52.1255730225948, 4.857260037781153 52.12489270966972, 4.857432505687366 52.12358885970951, 4.856966250193945 52.12318812892995, 4.857412305450096 52.12198214729695, 4.855523610331791 52.12072942129434, 4.855459491604404 52.1195211452892, 4.856410703395785 52.11874023894567, 4.857189725526387 52.11758407511068, 4.857006548770007 52.11648398314836, 4.858161027579516 52.11509998252357, 4.860588442243921 52.11558196309642, 4.862378153957152 52.11356052316284, 4.863167486792669 52.11317747763539, 4.862651303280372 52.11034849069802, 4.864831936661076 52.10842539029259, 4.864544590469517 52.1078322025319, 4.866034352158711 52.1062563318614, 4.867314973640948 52.10409968552982, 4.86967559135546 52.10353023647684, 4.865590360499596 52.09723068553979, 4.86211402445756 52.09595894201262, 4.861573683244572 52.09520757940017, 4.852430695728541 52.09876627241331, 4.846469734862426 52.10185569966663, 4.842415244351158 52.10297254568547, 4.837985745856069 52.10266207609867, 4.832555777932917 52.10394128701714, 4.831113012822775 52.10480424504518, 4.829541164175933 52.10500217933986, 4.82775049958501 52.10544065304562, 4.824631499045423 52.10542581163859, 4.825548195162908 52.10741128945562, 4.804847821873415 52.11667280734238))'
uuid = "1d65a4e1-ac2f-4e66-9e52-1d130d870a34"
raster_url = "https://nens.lizard.net/api/v4/rasters/"
get_url = f"{raster_url}{uuid}/curve/" #we gebruiken hier het endpoint curve
r = requests.get(
url=get_url,
headers=headers,
params=
{"geom": wkt,
#ruimtelijk aggregeren (niet nodig voor de dem)
#temporeel aggregeren (ook niet nodig voor de dem)
}
)
df_dem_distributie = pd.DataFrame(r.json()['results'], columns=['percentage', 'value'])
df_dem_distributie.set_index('percentage', inplace=True)
df_dem_distributie.plot(figsize=(20,7));
plt.legend('');
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.ylabel('Maaiveld [m NAP]', fontsize=20)
plt.xlabel('%', fontsize=20)
plt.title('Maaiveldcurve polder Zegveld', fontsize=20)
plt.show()
Stap 7 Hoogteligging door de tijd (BODIS)
Bij de vorige stap werd al genoemd dat de hoogteligging een belangrijke rol speelt voor een peilbesluit. Tegenwoordig hebben we ook te maken met bodemdaling, ofwel hoogteligging door de tijd. In het datawarehouse Lizard hebben we een raster "bodemdaling", ook wel BODIS genoemd die deels in de polder Zegveld data bevat. We kunnen van dit raster ook de bijbehorende informatie ophalen via de api voor een specifiek gebied. We kunnen voor de bodemdaling ook een curve tekenen, zodat de distributie beter zichtbaar wordt.
|
wkt = 'POLYGON ((4.804847821873415 52.11667280734238, 4.806713259859531 52.11808327571072, 4.805608147820809 52.11856102711491, 4.819366745114616 52.12916174862249, 4.820391627911995 52.12882844174937, 4.825146482688536 52.13155708895362, 4.836760218799797 52.1320950542045, 4.839831083487208 52.13138455359988, 4.841855268314998 52.13279519337573, 4.844997575437689 52.13266472167823, 4.851613567129445 52.13095545048285, 4.850995342194573 52.13013121164453, 4.855100260574258 52.12826534499285, 4.858115526952704 52.1255730225948, 4.857260037781153 52.12489270966972, 4.857432505687366 52.12358885970951, 4.856966250193945 52.12318812892995, 4.857412305450096 52.12198214729695, 4.855523610331791 52.12072942129434, 4.855459491604404 52.1195211452892, 4.856410703395785 52.11874023894567, 4.857189725526387 52.11758407511068, 4.857006548770007 52.11648398314836, 4.858161027579516 52.11509998252357, 4.860588442243921 52.11558196309642, 4.862378153957152 52.11356052316284, 4.863167486792669 52.11317747763539, 4.862651303280372 52.11034849069802, 4.864831936661076 52.10842539029259, 4.864544590469517 52.1078322025319, 4.866034352158711 52.1062563318614, 4.867314973640948 52.10409968552982, 4.86967559135546 52.10353023647684, 4.865590360499596 52.09723068553979, 4.86211402445756 52.09595894201262, 4.861573683244572 52.09520757940017, 4.852430695728541 52.09876627241331, 4.846469734862426 52.10185569966663, 4.842415244351158 52.10297254568547, 4.837985745856069 52.10266207609867, 4.832555777932917 52.10394128701714, 4.831113012822775 52.10480424504518, 4.829541164175933 52.10500217933986, 4.82775049958501 52.10544065304562, 4.824631499045423 52.10542581163859, 4.825548195162908 52.10741128945562, 4.804847821873415 52.11667280734238))'
uuid = "6f3389b5-5696-41d6-8a4c-ea9e2d548702"
raster_url = "https://nens.lizard.net/api/v4/rasters/"
get_url = f"{raster_url}{uuid}/curve/" #gebruik het endpoint curve
r = requests.get(
url=get_url,
headers=headers,
params=
{"geom": wkt,
#ruimtelijk aggregeren (niet nodig voor de dem)
#temporeel aggregeren (ook niet nodig voor de dem)
}
)
df_bodis = pd.DataFrame(r.json()['results'], columns=['percentage', 'value'])
df_bodis.set_index('percentage', inplace=True)
df_bodis.plot(figsize=(20,7));
plt.legend('');
plt.xticks(fontsize=20)
plt.yticks(fontsize=20)
plt.ylabel('Bodemdaling [mm/jaar]', fontsize=20)
plt.xlabel('%', fontsize=20)
plt.title('Bodemdaling curve polder Zegveld', fontsize=20)
plt.show()
Stap 8 Drooglegging
Eerder is er via een bodemtype tot een droogleggingsnorm gekomen. Drooglegging is het verschil tussen de hoogte van het maaiveld en het streefpeil (winter- of zomerpeil). Nu de data van de hoogteligging en het winter- en zomerpeil bekend is, kan de minimale en maximale drooglegging worden berekend en kan er worden gekeken of de droogleggingsnorm wordt behaald. We kunnen nu voor een specifiek punt in de polder de drooglegging berekenen tijdens zomerpeil en tijdens winterpeil. Welke data hebben we hiervoor nodig?
We doen dit door de rasterwaarde op een specifiek punt te extracten van het maaiveld raster.
|
|
|
De drooglegging wordt voor bovenstaand punt A in het poldergebied berekend. We halen eerst de maaiveldinformatie op van het punt A van het raster maaiveld. Vervolgens trekken we hier het zomer- en winterpeil nog vanaf om de waarde van de drooglegging te krijgen.
# polygoon shapefile boundaries polder zegveld
points = gpd.read_file('points.shp')
#in de geometrie van de polygoon zitten RD-coordinaten en die moeten voor de api call worden omgezet naar longitude, latitude
points.crs #hiermee kun je de informatie van de geometrie ophalen
points = points.to_crs("EPSG:4326") # geometrie omzetten naar juiste formaat ('EPSG:4326')
#print (points.geometry.all()) # juiste geometrie
wkt = 'POINT (4.857719746057215 52.10407919512313)'
uuid = "1d65a4e1-ac2f-4e66-9e52-1d130d870a34"
raster_url = "https://nens.lizard.net/api/v4/rasters/"
get_url = f"{raster_url}{uuid}/point/" # met het endpoint raster kun je de rasterwaarde van een bepaald punt terugkrijgen
r = requests.get(
url=get_url,
headers=headers,
params=
{"geom": wkt, #geef hier de coordinaten van het punt waarvan je de rasterwaarde wilt bepalen, op
#ruimtelijk aggregeren (niet nodig voor de dem)
#temporeel aggregeren (ook niet nodig voor de dem)
}
)
df = pd.DataFrame(r.json()['results'], columns=['point', 'value'])
print ('De drooglegging voor punt A tijdens het zomerpeil is gelijk aan het maaiveld op punt A', np.round(df['value'][0],2), 'minus', 'het gedefinieerde zomerpeil (NAP -2.33m)',':',
np.round(df['value'][0]--2.33,2), 'm')
print ('De drooglegging voor punt A tijdens het winterpeil is gelijk aan het maaiveld op punt A', np.round(df['value'][0],2), 'minus', 'het gedefinieerde winterpeil (NAP -2.43m)',':',
np.round(df['value'][0]--2.43,2), 'm')
Er was eerder bepaald dat de droogleggingsnorm tussen de 50 en 80 cm ligt voor polder Zegveld. En op dit specifieke punt moet de droogleggingsnorm 50 cm zijn (aangezien het bodemtype hier diep veen is). Dit wordt ongeveer gehaald tijdens het winterpeil en tijdens het zomerpeil zit het eronder. Hieruit kan worden vastgesteld dat het zomerpeil moet worden bijgesteld in het peilbesluit. Houd er wel rekening mee dat de bodemdaling data niet is meegenomen in deze korte analyse. Dit kan ook nog invloed hebben op deze analyse.
|
Conclusie
Met behup van het datawarehouse Lizard zijn we in staat om datasets met verschillende bronnen samen te brengen. Het verzamelen van de gegevens was altijd een tijdintensieve stap in het proces van een peilbesluit samenstellen. Vanuit het beeld van de API Economy is deze stap te vereenvoudigen, verbeteren en te versnellen.
Voor meer informatie kunt u contact opnemen met: