16 Extracting Interfaces from Geological Maps#

Geological Maps nowadays are usually available in a vector format consisting of connected polygons. These polygons consist of single vertices and hence, boundaries between younger and older stratigraphic units can be used for modeling. However, these specific vertices need to be kept while removing all unnecessary ones. The following will introduce how that works in GemGIS.

dee7b22643e64eb19c1d032d4b228139

Set File Paths and download Tutorial Data#

If you downloaded the latest GemGIS version from the Github repository, append the path so that the package can be imported successfully. Otherwise, it is recommended to install GemGIS via pip install gemgis and import GemGIS using import gemgis as gg. In addition, the file path to the folder where the data is being stored is set. The tutorial data is downloaded using Pooch (https://www.fatiando.org/pooch/latest/index.html) and stored in the specified folder. Use pip install pooch if Pooch is not installed on your system yet.

[1]:
import gemgis as gg

file_path ='data/16_extracting_interfaces_from_geological_maps/'
[2]:
gg.download_gemgis_data.download_tutorial_data(filename="16_extracting_interfaces_from_geological_maps.zip", dirpath=file_path)
Downloading file '16_extracting_interfaces_from_geological_maps.zip' from 'https://rwth-aachen.sciebo.de/s/AfXRsZywYDbUF34/download?path=%2F16_extracting_interfaces_from_geological_maps.zip' to 'C:\Users\ale93371\Documents\gemgis\docs\getting_started\tutorial\data\16_extracting_interfaces_from_geological_maps'.

Loading Data#

A simple geological map will be used to demonstrate the feature.

[3]:
import geopandas as gpd

gmap = gpd.read_file(file_path + 'interfaces_polygons.shp')
gmap
[3]:
id formation geometry
0 None Sand1 POLYGON ((0.25633 264.86215, 10.59347 276.7337...
1 None Ton POLYGON ((0.25633 264.86215, 0.18819 495.78721...
2 None Sand2 POLYGON ((0.18819 495.78721, 0.24897 1068.7595...
3 None Sand2 POLYGON ((511.67477 1068.85246, 971.69794 1068...
[4]:
import matplotlib.pyplot as plt

gmap.plot(column='formation', aspect='equal', legend=True)
plt.grid()
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_6_0.png

Sorting the GeoDataFrame by stratigraphic age#

The probably most important step of this workflow is to sort the stratigraphic units according to their age. This can be done using the function sort_by_stratigraphy(..) and by providing a list with the formations in stratigraphic order from young to old.

[5]:
stratigraphy = ['Sand2', 'Ton', 'Sand1']

gmap_sorted = gg.vector.sort_by_stratigraphy(gdf=gmap,
                                             stratigraphy=stratigraphy)

gmap_sorted
[5]:
id formation geometry
0 None Sand2 POLYGON ((0.18819 495.78721, 0.24897 1068.7595...
1 None Sand2 POLYGON ((511.67477 1068.85246, 971.69794 1068...
2 None Ton POLYGON ((0.25633 264.86215, 0.18819 495.78721...
3 None Sand1 POLYGON ((0.25633 264.86215, 10.59347 276.7337...

Extracting Intersections from Polygons#

The functionality is mainly based on the intersections between Shapely Polygons which will be demonstrated below.

Intersections between two polygons#

[6]:
gmap_sorted.loc[3].geometry
[6]:
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_11_0.svg
[7]:
gmap_sorted.loc[2].geometry
[7]:
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_12_0.svg
[8]:
intersection = gg.vector.intersection_polygon_polygon(polygon1=gmap_sorted.loc[3].geometry,
                                                      polygon2=gmap_sorted.loc[2].geometry)
intersection
[8]:
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_13_0.svg

Intersections between a polygon and polygons#

[9]:
gmap_sorted.loc[2].geometry
[9]:
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_15_0.svg
[10]:
poly_list=[gmap_sorted.loc[1].geometry, gmap_sorted.loc[0].geometry]
poly_list
[10]:
[<POLYGON ((511.675 1068.852, 971.698 1068.8, 971.738 832.976, 959.372 800.02...>,
 <POLYGON ((0.188 495.787, 0.249 1068.76, 278.524 1068.772, 265.602 1045.513,...>]
[11]:
intersection = gg.vector.intersections_polygon_polygons(polygon1=gmap_sorted.loc[2].geometry,
                                                        polygons2=poly_list)
intersection_gdf = gpd.GeoDataFrame(geometry=intersection)
intersection_gdf
[11]:
geometry
0 MULTILINESTRING ((511.675 1068.852, 526.375 10...
1 MULTILINESTRING ((0.188 495.787, 8.841 504.142...
[12]:
intersection_gdf.plot()
plt.grid()
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_18_0.png

Intersections between polygons and polygons#

[13]:
gdf1 = gpd.GeoDataFrame(geometry=[gmap_sorted.loc[2].geometry])
gdf1
[13]:
geometry
0 POLYGON ((0.256 264.862, 0.188 495.787, 8.841 ...
[14]:
gdf2 = gpd.GeoDataFrame(geometry=[gmap_sorted.loc[1].geometry, gmap_sorted.loc[0].geometry])
gdf2
[14]:
geometry
0 POLYGON ((511.675 1068.852, 971.698 1068.800, ...
1 POLYGON ((0.188 495.787, 0.249 1068.760, 278.5...
[15]:
intersection = gg.vector.intersections_polygons_polygons(polygons1=gdf1,
                                                         polygons2=gdf2)

intersection_gdf = gpd.GeoDataFrame(geometry=intersection)
intersection_gdf
[15]:
geometry
0 MULTILINESTRING ((511.675 1068.852, 526.375 10...
1 MULTILINESTRING ((0.188 495.787, 8.841 504.142...
[16]:
intersection_gdf.plot()
plt.grid()
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_23_0.png

Extracting Interfaces from Geological Map#

The final step is to use the entire GeoDataFrame for the extraction of the intersections. The resulting GeoDataFrame only contains interfaces of formations that also have a base. Therefore, interfaces of Sand1 are missing as this formation represents the basement of the stratigraphy.

[17]:
intersection = gg.vector.extract_xy_from_polygon_intersections(gdf=gmap_sorted)

intersection
[17]:
id formation geometry
0 None Sand2 MULTILINESTRING ((278.52378 1068.77171, 265.60...
1 None Sand2 MULTILINESTRING ((971.73811 832.97587, 959.372...
2 None Ton MULTILINESTRING ((972.08890 529.79176, 966.073...

When plotting the data, it can be seen that there are three different boundaries. First, there is the base of Ton and then twice the base of Sand2.

[18]:
intersection.plot(column='formation', aspect='equal', legend=True)
plt.grid()
../../_images/getting_started_tutorial_16_extracting_interfaces_from_geological_maps_27_0.png