This file is larger than 256 KB, so syntax highlighting was skipped.
{
"cells": [
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"/home/walch/.local/lib/python3.6/site-packages/dask/config.py:129: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.\n",
" data = yaml.load(f.read()) or {}\n",
"/home/walch/.local/lib/python3.6/site-packages/distributed/config.py:20: YAMLLoadWarning: calling yaml.load() without Loader=... is deprecated, as the default Loader is unsafe. Please read https://msg.pyyaml.org/load for full details.\n",
" defaults = yaml.load(f)\n"
]
}
],
"source": [
"import numpy as np\n",
"import pandas as pd\n",
"import geopandas as gpd\n",
"import xarray as xr\n",
"import contextily as ctx\n",
"\n",
"import os\n",
"import time\n",
"\n",
"%matplotlib notebook\n",
"import matplotlib.pyplot as plt\n",
"import matplotlib\n",
"import calendar\n",
"\n",
"from geo_util import *\n",
"from demand_mapping import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Loading data for electricity supply and demand in Geneva\n",
"This notebook gives an example for the reading, simple manipulation and visualisation of the electricity demand and PV potential data that we have available (for now). We use 3 main libraries:\n",
"- **pandas**: For reading .csv files, typically containing attributes of buildings, roofs etc.\n",
"- **geopandas**: For reading shapefiles, i.e. geospatial data (roof shapes, communes)\n",
"- **xarray**: For reading spatio-temporal data, i.e. data with a monthly-mean-hourly temporal resolution (288 timestamps) and a spatial resolution of building or roof instances (e.g. PV potential) "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [],
"source": [
"# Change this pathname depending on the location of the data\n",
"The PV potential is computed for each roof surface (~ 200k of them), which are identified by their *DF_UID*. The *DF_UID* represents the link between the annual and hourly files, as well as with the roof geometries.\n",
"\n",
"### Annual PV potential and available area\n",
"The annual potential file has multiple columns: The annual potential and its uncertainty (*std*), each in kWh/year; the solar radiation received by the tilted roof surface in kWh/m2/year, including shading effects, the available area, in m2, and a boolean variable indicating whether a roof is considered \"suitable\" based on the following definition: \n",
"- Roof tilt < 10° or roof aspect < 90° (southwards between east and west)\n",
"The hourly data as a netcdf file, for each DF_UID (even the non-suitable roofs) and for ~150 timestamps (all other timestamps are zero). The timestamps are given in the format 2001-[*MONTH*]-15 [*HOUR*]:00. It can be convenient to convert them to \"month\" and \"hour\" values or to integer indices (from 0 to 288), so I show here an example of how to do this.\n",
"integer_index = [hour + 24*(month - 1) for hour, month in zip(PV_hourly.hour.values, PV_hourly.month.values)]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Roof shapes\n",
"For the visualisation of the data, and for some further analysis, it is useful to obtain the roof shapes and their characteristics. For this task, we use **geopandas**:"
"Actually, most of the time not all columns are necessary. Those that are frequently of interest are the identifier of the underlying building (*SB_UUID*), the roof area (*FLAECHE*), tilt (*NEIGUNG*), and aspect (*AUSRICHTUN*) and the coordinates (*XCOORD, YCOORD*). The aspect is given in clockwise degrees from south (i.e. south = 0°, west = 90°, east = -90°). I have implemented a helper function (in the *libs* folder) that allows you to read only the relevant data subset."
"To visualise the PV potential geospatially, we can use the built-in functions of **geopandas**. For the visualisation of the temporal dimension, we can convert the **xarray** data (in aggregated form) to a pandas dataframe."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Geospatial manipulations\n",
"To visualise, for example, the technical PV potential on the suitable roofs, we can merge the annual PV potential information with the roof shapes:"
"We might further want to show only one commune, to reduce the number of roofs and make the visualisation more clear. For this, we can use the commune data (also a shapefile) and extract only central Geneva:"
"Now we need to extract the roof shape information only for the commune of interest. An efficient way to do this is to use a **spatial join**, an operation that allows to spatially merge data. We select all roofs that intersect with the commune of central Geneva:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [],
"source": [
"roof_PV_central_GE = gpd.sjoin(roof_PV, central_GE[['geometry']], op = 'intersects').drop(columns = ['index_right'])"
]
},
{
"cell_type": "code",
"execution_count": 15,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"36946"
]
},
"execution_count": 15,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"len(roof_PV_central_GE)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can also distinguish between suitable and unsuitable roofs:"
"To visualise, for example, the accumulated PV potential for the entire central Geneva (i.e. the commune shown above), we need to perform some more preprocessing steps:\n",
"The electrcity demand for ~45,000 buildings represents the residential and the service sector, without considering the electricity consumption used for electric heating and heatpumps (but this may change in the near future). Electricity demand is available for each of the buildings belonging to the residential and service sectors, based on the *Federal Register of Buildings and Dwellings* (Registre des bâtimens et logements, RegBL). These are not shapefiles but simply geographic locations (points); however, they can be mapped to buildings, which I can show you on demand. \n",
"\n",
"### RegBL base information\n",
"The basic RegBL information contains the location of a building, the building type and the principal sector (assigned based on the building type). An explanation of the data is provided in *buildings/RegBL_Codes.xlsx*. Each entry in the RegBL is identified by an **_EGID_**."
"The hourly electricity demand is available for the residential and service sectors separately, as well as the total demand, per EGID and given in W. We have weekday and weekend data, but for a start we will use a combined value that weighs weekend and weekdays. As the data is stored in a *netcdf* file, we use **xarray** to open it."
"To get the annual electricity demand, we have to multiply the daily values by the number of days of each month and sum them over the year. I have a helper function to do this: *get_yearly_sum*"
"We can also conver the coordinates of the RegBL to point data, such that it can be joined geospatially with the commune data. We have a helper function for this: *coords_to_point*"
"Now it's your turn: How can we display the annual demand data for the commune of central Geneva, and how can we plot the hourly demand together with the hourly potential, aggregated for the commune?"