© Alexander Jüstel, Fraunhofer IEG, Institution for Energy Infrastructures and Geothermal Systems, RWTH Aachen University, GNU Lesser General Public License v3.0

04 Processing Data Type 2 - Vector Polygons#

This notebook illustrates how to process data of Data Type 2 - Vector Polygons. The input data is provided as building polygons including the heat demand.

Importing Libraries#

[1]:
import rasterio
from rasterio.plot import show
import geopandas as gpd
from shapely.geometry import box
import matplotlib.pyplot as plt

from pyheatdemand import processing
C:\Users\ale93371\Anaconda3\envs\pygeomechanical\lib\site-packages\numpy\_distributor_init.py:30: UserWarning: loaded more than 1 DLL from .libs:
C:\Users\ale93371\Anaconda3\envs\pygeomechanical\lib\site-packages\numpy\.libs\libopenblas.FB5AE2TYXYH2IJRDKGDGQ3XBKLKTF43H.gfortran-win_amd64.dll
C:\Users\ale93371\Anaconda3\envs\pygeomechanical\lib\site-packages\numpy\.libs\libopenblas64__v0.3.23-246-g3d31191b-gcc_10_3_0.dll
  warnings.warn("loaded more than 1 DLL from .libs:"

Loading Sample Data#

The sample data is loaded using GeoPandas.

[2]:
data = gpd.read_file('../../../test/data/Data_Type_II_Vector_cropped.shp')
data.head()
[2]:
WB_HU geometry
0 831.567994 POLYGON Z ((294937.742 5628264.825 0.000, 2949...
1 15792.140231 POLYGON Z ((294257.760 5628116.788 0.000, 2942...
2 8408.132992 POLYGON Z ((294805.340 5628284.175 0.000, 2948...
3 3174.220399 POLYGON Z ((294968.972 5628185.682 0.000, 2949...
4 184658.547969 POLYGON Z ((294361.812 5628639.678 0.000, 2943...
[3]:
fig, ax = plt.subplots(1, figsize=(10,10))

data.plot(column='WB_HU', ax=ax, legend=True, legend_kwds={'shrink':0.55, 'label': 'Heat Demand [MWh]'})

ax.set_xlabel('X [m]')
ax.set_ylabel('Y [m]')
[3]:
Text(61.347222222222214, 0.5, 'Y [m]')
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_5_1.png

Inspect CRS#

We are inspecting the CRS and see that is does not match with the desired CRS EPSG:3034.

[4]:
data.crs
[4]:
<Projected CRS: EPSG:25832>
Name: ETRS89 / UTM zone 32N
Axis Info [cartesian]:
- E[east]: Easting (metre)
- N[north]: Northing (metre)
Area of Use:
- name: Europe between 6°E and 12°E: Austria; Belgium; Denmark - onshore and offshore; Germany - onshore and offshore; Norway including - onshore and offshore; Spain - offshore.
- bounds: (6.0, 38.76, 12.01, 84.33)
Coordinate Operation:
- name: UTM zone 32N
- method: Transverse Mercator
Datum: European Terrestrial Reference System 1989 ensemble
- Ellipsoid: GRS 1980
- Prime Meridian: Greenwich

Reprojecting CRS#

The CRS of the data is reprojected to the desired CRS EPSG:3034.

[5]:
data = data.to_crs('EPSG:3034')

Creating GeoDataFrame Outline from vectorized Raster#

For further processing, we are creating an outline GeoDataFrame from the total_bounds of the vectorized raster.

[6]:
gdf = processing.create_outline(data)
gdf
[6]:
geometry
0 POLYGON ((3735113.300 2674169.060, 3735113.300...

Loading Interreg Mask#

We are loading the previously created 10 km mask.

[7]:
mask_10km = gpd.read_file('../../../test/data/Interreg_NWE_mask_10km_3034.shp')
mask_10km
[7]:
FID geometry
0 0 POLYGON ((2651470.877 2955999.353, 2651470.877...
1 1 POLYGON ((2651470.877 2965999.353, 2651470.877...
2 2 POLYGON ((2651470.877 2975999.353, 2651470.877...
3 3 POLYGON ((2651470.877 2985999.353, 2651470.877...
4 4 POLYGON ((2651470.877 2995999.353, 2651470.877...
... ... ...
9225 9225 POLYGON ((4141470.877 2605999.353, 4141470.877...
9226 9226 POLYGON ((4141470.877 2615999.353, 4141470.877...
9227 9227 POLYGON ((4151470.877 2585999.353, 4151470.877...
9228 9228 POLYGON ((4151470.877 2595999.353, 4151470.877...
9229 9229 POLYGON ((4151470.877 2605999.353, 4151470.877...

9230 rows × 2 columns

[8]:
mask_10km.crs
[8]:
<Projected CRS: EPSG:3034>
Name: ETRS89-extended / LCC Europe
Axis Info [cartesian]:
- N[north]: Northing (metre)
- E[east]: Easting (metre)
Area of Use:
- name: Europe - European Union (EU) countries and candidates. Europe - onshore and offshore: Albania; Andorra; Austria; Belgium; Bosnia and Herzegovina; Bulgaria; Croatia; Cyprus; Czechia; Denmark; Estonia; Faroe Islands; Finland; France; Germany; Gibraltar; Greece; Hungary; Iceland; Ireland; Italy; Kosovo; Latvia; Liechtenstein; Lithuania; Luxembourg; Malta; Monaco; Montenegro; Netherlands; North Macedonia; Norway including Svalbard and Jan Mayen; Poland; Portugal including Madeira and Azores; Romania; San Marino; Serbia; Slovakia; Slovenia; Spain including Canary Islands; Sweden; Switzerland; Türkiye (Turkey); United Kingdom (UK) including Channel Islands and Isle of Man; Vatican City State.
- bounds: (-35.58, 24.6, 44.83, 84.73)
Coordinate Operation:
- name: Europe Conformal 2001
- method: Lambert Conic Conformal (2SP)
Datum: European Terrestrial Reference System 1989 ensemble
- Ellipsoid: GRS 1980
- Prime Meridian: Greenwich
[9]:
fig, ax = plt.subplots(figsize=(10,10))
mask_10km.boundary.plot(ax=ax, linewidth=1, color='green')
plt.xlabel('X [m]')
plt.ylabel('Y [m]')
plt.grid()
plt.tight_layout()
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_15_0.png

Crop Mask to Data Limits#

The 10 km cells that intersect with the data outline are selected.

[10]:
mask_10km_cropped = mask_10km.sjoin(gdf).reset_index()[['geometry']]
mask_10km_cropped
[10]:
geometry
0 POLYGON ((3731470.877 2665999.353, 3731470.877...
1 POLYGON ((3731470.877 2675999.353, 3731470.877...
2 POLYGON ((3731470.877 2665999.353, 3731470.877...
3 POLYGON ((3731470.877 2675999.353, 3731470.877...

Plotting the Cropped Mask#

The cropped mask and the data outline are plotted using matplotlib.

[11]:
fig, ax = plt.subplots(figsize=(10,10))
mask_10km_cropped.boundary.plot(ax=ax, linewidth=3, color='green')
gdf.to_crs('EPSG:3034').boundary.plot(ax=ax, linewidth=3)
plt.xlabel('X [m]')
plt.ylabel('Y [m]')
plt.grid()
plt.tight_layout()
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_19_0.png

Creating mask from cropped mask#

Here, the final mask with a width and height of 100 m is created.

[12]:
mask_100m_cropped = processing.create_polygon_mask(gdf=mask_10km_cropped,
                                                   step_size=100,
                                                   crop_gdf=True)
mask_100m_cropped
[12]:
geometry
0 POLYGON ((3731470.877 2665999.353, 3731570.877...
1 POLYGON ((3731470.877 2666099.353, 3731570.877...
2 POLYGON ((3731470.877 2666199.353, 3731570.877...
3 POLYGON ((3731470.877 2666299.353, 3731570.877...
4 POLYGON ((3731470.877 2666399.353, 3731570.877...
... ...
40395 POLYGON ((3741370.877 2685499.353, 3741470.877...
40396 POLYGON ((3741370.877 2685599.353, 3741470.877...
40397 POLYGON ((3741370.877 2685699.353, 3741470.877...
40398 POLYGON ((3741370.877 2685799.353, 3741470.877...
40399 POLYGON ((3741370.877 2685899.353, 3741470.877...

40400 rows × 1 columns

mask_100m.to_file('../data/Interreg_NWE_mask_500m_EPSG3034.shp')

Cropping Mask to outline#

[13]:
fig, ax = plt.subplots(figsize=(10,10))
mask_10km_cropped.boundary.plot(ax=ax, linewidth=3, color='green')
gdf.to_crs('EPSG:3034').boundary.plot(ax=ax, linewidth=3)
mask_100m_cropped.boundary.plot(ax=ax, linewidth=0.5, color='green')
plt.xlabel('X [m]')
plt.ylabel('Y [m]')
plt.grid()
plt.tight_layout()

#plt.savefig('../images/Data_Type_1_Outline.png', dpi=300)
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_24_0.png
[14]:
fig, ax = plt.subplots(figsize=(10,10))

mask_100m_cropped.boundary.plot(ax=ax, linewidth=0.5, color='green')
data.plot(ax=ax, column='WB_HU', legend=True, legend_kwds={'shrink':0.7, 'label': 'Heat Demand [MWh]'})
plt.xlabel('X [m]')
plt.ylabel('Y [m]')
plt.grid()
plt.tight_layout()
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_25_0.png

Calculate Heat Demand#

With the vectorized raster and the 100 m mask, we can now directly calculate the heat demand using calculate_hd.

[15]:
hd_gdf = data
mask_gdf = mask_100m_cropped
[16]:
gdf_hd = processing.calculate_hd(hd_gdf,
                                 mask_gdf,
                                 'WB_HU')
gdf_hd
[16]:
HD geometry
0 1.020856e+03 POLYGON ((3731670.877 2675799.353, 3731770.877...
1 2.117455e+05 POLYGON ((3731670.877 2675899.353, 3731770.877...
2 2.426676e+05 POLYGON ((3731770.877 2674299.353, 3731870.877...
3 4.839702e+04 POLYGON ((3731770.877 2674399.353, 3731870.877...
4 1.248658e+05 POLYGON ((3731770.877 2674499.353, 3731870.877...
... ... ...
731 1.945455e+06 POLYGON ((3734970.877 2676099.353, 3735070.877...
732 2.759468e+06 POLYGON ((3734970.877 2676199.353, 3735070.877...
733 4.305813e+05 POLYGON ((3734970.877 2676299.353, 3735070.877...
734 1.701362e+05 POLYGON ((3735070.877 2676099.353, 3735170.877...
735 3.159179e+04 POLYGON ((3735070.877 2676199.353, 3735170.877...

736 rows × 2 columns

[17]:
fig, ax = plt.subplots(figsize=(10,10))

gdf_hd.plot(column='HD', ax=ax, legend=True, legend_kwds={'shrink':0.51, 'label': 'Heat Demand [MWh]'})

plt.xlabel('X [m]')
plt.ylabel('Y [m]')
[17]:
Text(61.347222222222214, 0.5, 'Y [m]')
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_29_1.png

Rasterizing Vector Data#

The vector data will be rasterized and saved to file.

[18]:
processing.rasterize_gdf_hd(gdf_hd,
                     path_out='../../../test/data/Data_Type_II_Vector.tif',
                     crs = 'EPSG:3034',
                     xsize = 100,
                     ysize = 100,
                     flip_raster=True)

Opening and plotting raster#

The final raster can now be opened and plotted.

[19]:
raster = rasterio.open('../../../test/data/Data_Type_II_Vector.tif')
[20]:
show(raster)
../_images/notebooks_04_Processing_Data_Type_II_Vector_Polygons_34_0.png
[20]:
<Axes: >