In [1]:
%matplotlib inline
import inspect, sys
In [2]:
# check pydov path
import pydov
In [3]:
from pydov.search.grondmonster import GrondmonsterSearch
grondmonster = GrondmonsterSearch()
A description is provided for the 'Grondmonster' datatype:
In [4]:
print(grondmonster.get_description())
The different fields that are available for objects of the 'Grondmonster' datatype can be requested with the get_fields() method:
In [5]:
fields = grondmonster.get_fields()
# print available fields
for f in fields.values():
print(f['name'])
You can get more information of a field by requesting it from the fields dictionary:
In [6]:
fields['chemisch']
Out[6]:
Get data for all the boreholes 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.
In [7]:
from pydov.util.location import Within, Box
df = grondmonster.search(location=Within(Box(122000, 187000, 124000, 189000)))
df.head()
Out[7]:
The dataframe contains borehole samples from 6 boreholes The available data are flattened to represent unique attributes per row of the dataframe.
Using the pkey_grondmonster field one can request the details of this borehole in a webbrowser: https://www.dov.vlaanderen.be/data/grondmonster/*pkey_grondmonster*
In [8]:
for pkey_grondmonster in set(df.loc[df.boornummer == 'GEO-02/028-B5'].pkey_grondmonster):
print(pkey_grondmonster)
There were 10 samples taken from the above borehole, each identified by its own URI.
Next to querying borehole samples based on their geographic location within a bounding box, we can also search for borehole samples matching a specific set of properties. For this we can build a query using a combination of the 'Grondmonster' fields and operators provided by the WFS protocol.
A list of possible operators can be found below:
In [9]:
[i for i,j in inspect.getmembers(sys.modules['owslib.fes'], inspect.isclass) if 'Property' in i]
Out[9]:
In this example we build a query using the PropertyIsEqualTo operator to find all boreholes that are within the community (gemeente) of 'Wichelen':
In [10]:
from owslib.fes import PropertyIsEqualTo
query = PropertyIsEqualTo(propertyname='gemeente',
literal='Wichelen')
df = grondmonster.search(query=query)
df.head()
Out[10]:
Once again we can use the pkey_grondmonster as a permanent link to the information of these boreholes:
In [11]:
for pkey_grondmonster in set(df.loc[df.boornummer == 'GEO-04/022-B4'].pkey_grondmonster):
print(pkey_grondmonster)
We can combine a query on attributes with a query on geographic location to get the borehole samples within a bounding box that have specific properties.
The following example requests the borehole samples with a depth greater than or equal to 15 meters within the given bounding box.
(Note that the datatype of the literal parameter should be a string, regardless of the datatype of this field in the output dataframe.)
In [12]:
from owslib.fes import PropertyIsGreaterThanOrEqualTo
query = PropertyIsGreaterThanOrEqualTo(
propertyname='diepte_tot_m',
literal='15')
df = grondmonster.search(
location=Within(Box(122000, 187000, 124000, 189000)),
query=query
)
df.head()
Out[12]:
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 borehole samples in the city of Ghent and return their depth:
In [13]:
query = PropertyIsEqualTo(propertyname='gemeente',
literal='Gent')
df = grondmonster.search(query=query,
return_fields=('diepte_tot_m',))
df.head()
Out[13]:
In [14]:
df.describe()
Out[14]:
In [15]:
ax = df[df.diepte_tot_m != 0].boxplot()
ax.set_ylabel("depth (m)")
ax.set_title("Depth distribution borehole samples in Gent")
Out[15]:
To keep the output dataframe size acceptable, not all available WFS fields are included in the standard output. However, one can use this information to select borehole samples as illustrated below.
For example, make a selection of the borehole samples in the municipality of Antwerp, for which a mechanical test was carried out
In [16]:
from owslib.fes import And
query = And([PropertyIsEqualTo(propertyname='gemeente',
literal='Antwerpen'),
PropertyIsEqualTo(propertyname='mechanisch',
literal='True')]
)
df = grondmonster.search(query=query,
return_fields=('pkey_grondmonster', 'boornummer', 'x', 'y'))
df.head()
Out[16]:
The data from the mechanical tests are not always available through the webservice. Following the URI of the borehole sample, one can access the available information in the subtype 'mechanisch'.
In [17]:
for pkey_grondmonster in set(df.loc[df.boornummer=='1445-GEO-17/047-B211'].pkey_grondmonster):
print(pkey_grondmonster)
Using Folium, we can display the results of our search on a map.
In [18]:
# import the necessary modules (not included in the requirements of pydov!)
import folium
from folium.plugins import MarkerCluster
from pyproj import Transformer
In [19]:
# convert the coordinates to lat/lon for folium
def convert_latlon(x1, y1):
transformer = Transformer.from_crs("epsg:31370", "epsg:4326", always_xy=True)
x2,y2 = transformer.transform(x1, y1)
return x2, y2
df['lon'], df['lat'] = zip(*map(convert_latlon, df['x'], df['y']))
# convert to list
loclist = df[['lat', 'lon']].values.tolist()
In [20]:
# initialize the Folium map on the centre of the selected locations, play with the zoom until ok
fmap = folium.Map(location=[df['lat'].mean(), df['lon'].mean()], zoom_start=12)
marker_cluster = MarkerCluster().add_to(fmap)
for loc in range(0, len(loclist)):
folium.Marker(loclist[loc], popup=df['boornummer'][loc]).add_to(marker_cluster)
fmap
Out[20]: