diff --git a/README.md b/README.md index 7acabaa72..576873302 100644 --- a/README.md +++ b/README.md @@ -116,38 +116,31 @@ The documentation is available here: [documentation](https://pypsa-meets-africa. - - - + + - - - - - - -
- - hazemakhalek -
- Hazemakhalek -
-
- - jarry7 + + pz-max
- Jarrad Wright + Max Parzen
- - fneum + + davide-f
- Fabian Neumann + Davide-f
- - euronion + + restyled-commits
- Euronion + Restyled Commits
- - Justus-coded + + ekatef
- Justus Ilemobayo + Ekaterina
@@ -156,56 +149,41 @@ The documentation is available here: [documentation](https://pypsa-meets-africa.
Mnm-matin -
- - desenk -
- Desen Kirli -
- - LukasFrankenQ + + Hazem-IEG
- Lukas Franken + Hazem-IEG
-
- - pz-max + + euronion
- Max Parzen + Euronion
- - Cesare-Caputo + + giacfalk
- Cesare-Caputo + Giacomo Falchetta
- - Nayara2020 + + LukasFrankenQ
- Nayara2020 + Lukas Franken
- - Ay-Khi -
- Ayman Alkhirbash -
-
- - davide-f + + Tooblippe
- Davide-f + Jarrad Wright
@@ -216,48 +194,13 @@ The documentation is available here: [documentation](https://pypsa-meets-africa. - - Hazem-IEG -
- Hazem-IEG -
-
- - energyLS -
- EnergyLS -
-
- - restyled-commits -
- Restyled Commits -
-
- - ekatef + + jarry7
- Ekaterina + Jarrad Wright
- - giacfalk -
- Giacomo Falchetta -
-
- - Tooblippe -
- Jarrad Wright -
-
EmreYorat diff --git a/notebooks/augmented_line_connections.ipynb b/notebooks/augmented_line_connections.ipynb new file mode 100644 index 000000000..04c65963d --- /dev/null +++ b/notebooks/augmented_line_connections.ipynb @@ -0,0 +1,539 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Augmented line connections\n", + "\n", + "This notebook will compare the original, clustered and augmented line network.\n", + "To reproduce the images, run the workflow with the augmented line connection.\n", + "\n", + "```python\n", + "augmented_line_connection:\n", + " add_to_snakefile: true # If True, includes this rule to the workflow\n", + "```" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Parameters and imports" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Python imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import xarray as xr\n", + "import geopandas as gpd\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib\n", + "import numpy as np\n", + "import requests\n", + "import pypsa\n", + "import shutil\n", + "from rasterio.plot import show\n", + "from shapely.wkt import loads\n", + "from shapely.geometry import Point\n", + "from shapely.geometry import LineString\n", + "\n", + "import os\n", + "import sys\n", + "\n", + "sys.path.append(\"../\") # to import helpers\n", + "from scripts._helpers import sets_path_to_root\n", + "\n", + "sets_path_to_root(\"pypsa-africa\")\n", + "sys.path.append(\"./scripts\") # to import helpers\n", + "from download_osm_data import create_country_list" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Paths\n", + "\n", + "The below paths are required to generate the images. We use wildcards from glob to access multiple paths. '*' is interpreted as any value for any number of characters. '?' is interpreted as any value for only one character.\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import glob\n", + "\n", + "# network paths\n", + "path_networks = glob.glob(\"networks/elec_s_*nc\")\n", + "clustered_network = path_networks[0]\n", + "simplified_network = path_networks[1]\n", + "pre_augmented_network = path_networks[2]\n", + "augmented_network = path_networks[3]\n", + "path_networks\n", + "\n", + "# Example output\n", + "# ['networks/elec_s_420.nc',\n", + "# 'networks/elec_s_420_ec.nc',\n", + "# 'networks/elec_s_420_pre_augmentation.nc',\n", + "# 'networks/elec_s_420_ec_lcopt_Co2L-24.nc']" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Paths of build shapes\n", + "path_country_shapes = \"resources/country_shapes.geojson\"\n", + "path_offshore_shapes = \"resources/offshore_shapes.geojson\"\n", + "path_gadm_shapes = \"resources/gadm_shapes.geojson\"\n", + "path_cluster_shape_on = glob.glob(\"resources/regions_onshore_elec_s_*.geojson\")[0]\n", + "path_cluster_shape_off = glob.glob(\"resources/regions_offshore_elec_s_*.geojson\")[0]\n", + "\n", + "# Path of the OSM data\n", + "path_raw_substations = \"data/raw/africa_all_raw_substations.geojson\"\n", + "path_raw_lines = \"data/raw/africa_all_raw_lines.geojson\"" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# Images setups\n", + "max_width_image = 15\n", + "max_height_image = 15\n", + "dpi = 300" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Auxiliary functions" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_width_height_image(\n", + " width_image, height_image, max_width=max_width_image, max_height=max_height_image\n", + "):\n", + " \"\"\"\n", + " Function to identify the width and height of an image to plot\n", + " while keeping the proportions of the image\n", + " \"\"\"\n", + " if width_image / height_image >= max_width / max_height:\n", + " # image width is the limiting factor\n", + " return (width_image, max_width / width_image * height_image)\n", + " else:\n", + " # image height is the limiting factor\n", + " return (max_height / height_image * width_image, max_height)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### File imports" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# gadm file imports\n", + "countries = gpd.read_file(path_country_shapes)\n", + "off_shore = gpd.read_file(path_offshore_shapes)\n", + "gadm = gpd.read_file(path_gadm_shapes)\n", + "cluster_shape_on = gpd.read_file(path_cluster_shape_on)\n", + "cluster_shape_off = gpd.read_file(path_cluster_shape_off)\n", + "\n", + "# OSM data imports\n", + "df_substations_osm_raw = gpd.read_file(path_raw_substations)\n", + "df_lines_osm_raw = gpd.read_file(path_raw_lines)\n", + "\n", + "# network imports\n", + "n_cluster = pypsa.Network(clustered_network)\n", + "n_simple = pypsa.Network(simplified_network)\n", + "n_preaugmented = pypsa.Network(pre_augmented_network)\n", + "n_augmented = pypsa.Network(augmented_network)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Continent and raw OSM data" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot for the entire area downloaded" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import contextily as cx # Need to be installed `pip3 install contextily`\n", + "from matplotlib import cm\n", + "import matplotlib.pyplot as plt\n", + "import matplotlib as mpl\n", + "\n", + "total_bounds_countries = countries.total_bounds\n", + "delta_bounds_xy = (\n", + " total_bounds_countries[2] - total_bounds_countries[0], # maxx - minx\n", + " total_bounds_countries[3] - total_bounds_countries[1],\n", + ") # maxy - miny\n", + "\n", + "size_image = calculate_width_height_image(*delta_bounds_xy)\n", + "\n", + "ax2 = gadm.plot(\n", + " column=\"pop\",\n", + " cmap=\"OrRd\",\n", + " figsize=size_image,\n", + " legend=False,\n", + " norm=matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() + 1, vmax=gadm[\"pop\"].max(), clip=True\n", + " ),\n", + ")\n", + "# ax2 = cluster_shape_on.plot(figsize=size_image, legend=None)\n", + "cluster_shape_off.plot(ax=ax2, label=\"offshore\")\n", + "df_lines_osm_raw.plot(ax=ax2, color=\"navy\", label=\"OSM lines\")\n", + "df_substations_osm_raw.plot(\n", + " ax=ax2, color=\"papayawhip\", alpha=0.7, markersize=5, label=\"OSM substations\"\n", + ")\n", + "\n", + "\n", + "# Colorbar\n", + "cmap = \"OrRd\"\n", + "norm = matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() / 1000 + 1, vmax=gadm[\"pop\"].max() / 1000, clip=True\n", + ")\n", + "cbar = plt.colorbar(\n", + " mpl.cm.ScalarMappable(norm=norm, cmap=cmap),\n", + " ax=ax2,\n", + " orientation=\"vertical\",\n", + " extend=\"max\",\n", + " shrink=0.6,\n", + ")\n", + "cbar.set_label(\"Population/1000 in administrative zones\", fontsize=16, color=\"dimgrey\")\n", + "\n", + "\n", + "plt.axis(\"off\")\n", + "\n", + "plt.rc(\"legend\", fontsize=13)\n", + "ax2.legend(\n", + " bbox_to_anchor=(1.035, 0.95),\n", + " borderaxespad=0,\n", + " facecolor=\"#1f77b4\",\n", + " framealpha=0.9,\n", + " labelcolor=\"white\",\n", + ")\n", + "plt.savefig(\"build-osm-network-africa.pdf\", bbox_inches=\"tight\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Plot for a subregion specified by a string as in \"countries\" config" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = [\"NG\"]\n", + "\n", + "list_countries = create_country_list(region)\n", + "\n", + "ax2 = gadm[gadm.country.isin(list_countries)].plot(\n", + " column=\"pop\",\n", + " cmap=\"OrRd\",\n", + " figsize=size_image,\n", + " legend=None,\n", + " norm=matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() + 1, vmax=gadm[\"pop\"].max(), clip=True\n", + " ),\n", + ") # column=\"pop\",\n", + "off_shore[off_shore.name.isin(list_countries)].plot(ax=ax2, label=\"offshore\")\n", + "df_lines_osm_raw[df_lines_osm_raw.Country.isin(list_countries)].plot(\n", + " ax=ax2, color=\"navy\"\n", + ")\n", + "df_substations_osm_raw[df_substations_osm_raw.Country.isin(list_countries)].plot(\n", + " ax=ax2, color=\"papayawhip\", alpha=0.7, markersize=15\n", + ")\n", + "\n", + "# Colorbar\n", + "cmap = \"OrRd\"\n", + "norm = matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() / 1000 + 1, vmax=gadm[\"pop\"].max() / 1000, clip=True\n", + ")\n", + "cbar = plt.colorbar(\n", + " mpl.cm.ScalarMappable(norm=norm, cmap=cmap),\n", + " ax=ax2,\n", + " orientation=\"vertical\",\n", + " extend=\"max\",\n", + " shrink=0.6,\n", + ")\n", + "cbar.set_label(\"Population/1000 in administrative zones\", fontsize=16, color=\"dimgrey\")\n", + "\n", + "plt.axis(\"off\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Cluster network" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### EXTRACT DATA FIRST OF PYPSA NETWORK\n", + "\n", + "# Options\n", + "# clustered_network = path_networks[0]\n", + "# simplified_network = path_networks[1]\n", + "# pre_augmented_network = path_networks[2]\n", + "# augmented_network = path_networks[3]\n", + "\n", + "# buses dataframe\n", + "buses_c = n_cluster.buses\n", + "buses_c[\"geometry\"] = gpd.points_from_xy(buses_c.x, buses_c.y)\n", + "buses_c = gpd.GeoDataFrame(buses_c, crs=\"epsg:4326\")\n", + "\n", + "# lines dataframe\n", + "lines_c = n_cluster.lines\n", + "lines_c[\"geometry\"] = lines_c.apply(\n", + " lambda x: LineString(\n", + " [buses_c.loc[x[\"bus0\"], \"geometry\"], buses_c.loc[x[\"bus1\"], \"geometry\"]]\n", + " ),\n", + " axis=1,\n", + ")\n", + "lines_c = gpd.GeoDataFrame(lines_c, crs=\"epsg:4326\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "### Plot cluster network" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = [\"Africa\"]\n", + "list_countries = create_country_list(region)\n", + "\n", + "ax2 = gadm[gadm.country.isin(list_countries)].plot(\n", + " column=\"pop\",\n", + " cmap=\"OrRd\",\n", + " figsize=size_image,\n", + " legend=None,\n", + " norm=matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() + 1, vmax=gadm[\"pop\"].max(), clip=True\n", + " ),\n", + ") # column=\"pop\",\n", + "off_shore[off_shore.name.isin(list_countries)].plot(ax=ax2, label=\"offshore\")\n", + "\n", + "\n", + "lines_c.plot(ax=ax2, color=\"navy\", label=\"Clustered lines\")\n", + "buses_c.plot(\n", + " ax=ax2, color=\"papayawhip\", alpha=0.9, markersize=15, label=\"Clustered substations\"\n", + ")\n", + "\n", + "\n", + "# Colorbar\n", + "cmap = \"OrRd\"\n", + "norm = matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() / 1000 + 1, vmax=gadm[\"pop\"].max() / 1000, clip=True\n", + ")\n", + "cbar = plt.colorbar(\n", + " mpl.cm.ScalarMappable(norm=norm, cmap=cmap),\n", + " ax=ax2,\n", + " orientation=\"vertical\",\n", + " extend=\"max\",\n", + " shrink=0.6,\n", + ")\n", + "cbar.set_label(\"Population/1000 in administrative zones\", fontsize=16, color=\"dimgrey\")\n", + "\n", + "plt.axis(\"off\")\n", + "plt.rc(\"legend\", fontsize=13)\n", + "ax2.legend(\n", + " bbox_to_anchor=(1.035, 0.95),\n", + " borderaxespad=0,\n", + " facecolor=\"#1f77b4\",\n", + " framealpha=0.9,\n", + " labelcolor=\"white\",\n", + ")\n", + "plt.savefig(\"420-clustered-network-africa.pdf\", bbox_inches=\"tight\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Augmented network" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "### Creates a LineString of the Augmented lines\n", + "\n", + "# buses dataframe\n", + "buses_c = n_augmented.buses\n", + "buses_c[\"geometry\"] = gpd.points_from_xy(buses_c.x, buses_c.y)\n", + "buses_c = gpd.GeoDataFrame(buses_c, crs=\"epsg:4326\")\n", + "\n", + "# lines dataframe\n", + "lines_c = n_augmented.lines\n", + "lines_c[\"geometry\"] = lines_c.apply(\n", + " lambda x: LineString(\n", + " [buses_c.loc[x[\"bus0\"], \"geometry\"], buses_c.loc[x[\"bus1\"], \"geometry\"]]\n", + " ),\n", + " axis=1,\n", + ")\n", + "lines_c = gpd.GeoDataFrame(lines_c, crs=\"epsg:4326\")\n", + "\n", + "# links dataframe\n", + "links_c = n_augmented.links\n", + "links_c[\"geometry\"] = np.nan\n", + "for i in range(len(n_augmented.links.bus0)):\n", + " n_augmented.links.iloc[i, -1] = LineString(\n", + " [\n", + " n_augmented.buses.loc[\n", + " n_augmented.buses.index == n_augmented.links.bus0[i], \"geometry\"\n", + " ][0],\n", + " n_augmented.buses.loc[\n", + " n_augmented.buses.index == n_augmented.links.bus1[i], \"geometry\"\n", + " ][0],\n", + " ]\n", + " )\n", + "links_c = gpd.GeoDataFrame(n_augmented.links, crs=\"epsg:4326\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "region = [\"Africa\"]\n", + "list_countries = create_country_list(region)\n", + "\n", + "ax2 = gadm[gadm.country.isin(list_countries)].plot(\n", + " column=\"pop\",\n", + " cmap=\"OrRd\",\n", + " figsize=size_image,\n", + " legend=None,\n", + " norm=matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() + 1, vmax=gadm[\"pop\"].max(), clip=True\n", + " ),\n", + ") # column=\"pop\",\n", + "off_shore[off_shore.name.isin(list_countries)].plot(ax=ax2, label=\"offshore\")\n", + "\n", + "lines_c.plot(ax=ax2, color=\"navy\", label=\"Clustered lines\")\n", + "links_c.plot(\n", + " ax=ax2, color=\"springgreen\", linewidth=5, alpha=0.7, label=\"Augmented lines\"\n", + ")\n", + "buses_c.plot(\n", + " ax=ax2, color=\"papayawhip\", alpha=1, markersize=15, label=\"Clustered substations\"\n", + ")\n", + "\n", + "# Colorbar\n", + "cmap = \"OrRd\"\n", + "norm = matplotlib.colors.LogNorm(\n", + " vmin=gadm[\"pop\"].min() / 1000 + 1, vmax=gadm[\"pop\"].max() / 1000, clip=True\n", + ")\n", + "cbar = plt.colorbar(\n", + " mpl.cm.ScalarMappable(norm=norm, cmap=cmap),\n", + " ax=ax2,\n", + " orientation=\"vertical\",\n", + " extend=\"max\",\n", + " shrink=0.6,\n", + ")\n", + "cbar.set_label(\"Population/1000 in administrative zones\", fontsize=16, color=\"dimgrey\")\n", + "\n", + "plt.axis(\"off\")\n", + "\n", + "plt.rc(\"legend\", fontsize=13)\n", + "ax2.legend(\n", + " bbox_to_anchor=(0.75, 0.95),\n", + " borderaxespad=0,\n", + " facecolor=\"#1f77b4\",\n", + " framealpha=0.9,\n", + " labelcolor=\"white\",\n", + ")\n", + "plt.savefig(\"420-augmented-line-africa.pdf\", bbox_inches=\"tight\")" + ] + } + ], + "metadata": { + "interpreter": { + "hash": "93061c673ce33a785d7c590269df2a13242973b51d41b0d96d8b2a166e219992" + }, + "kernelspec": { + "display_name": "Python 3.9.7 64-bit ('pypsa-africa': conda)", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.4" + }, + "orig_nbformat": 4 + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/notebooks/validation/network_validation.ipynb b/notebooks/validation/network_validation.ipynb index 4ad4cac05..9d16726ec 100644 --- a/notebooks/validation/network_validation.ipynb +++ b/notebooks/validation/network_validation.ipynb @@ -461,7 +461,7 @@ "import matplotlib as mpl\n", "\n", "# adapt all sizes\n", - "size = 1\n", + "size = 0.5\n", "# Create the basemap that is called by ax\n", "ax = africa_shape.to_crs(epsg=\"3857\").plot(\n", " figsize=(20 * size, 20 * size), alpha=0.5, facecolor=\"white\", edgecolor=\"whitesmoke\"\n", @@ -517,7 +517,9 @@ "# ticks & edge modification of cbar\n", "cbar.ax.yaxis.set_tick_params(color=\"grey\")\n", "plt.setp(plt.getp(cbar.ax.axes, \"yticklabels\"), color=\"dimgrey\")\n", - "cbar.outline.set_edgecolor(None) # set colorbar edgecolor" + "cbar.outline.set_edgecolor(None) # set colorbar edgecolor\n", + "\n", + "# plt.savefig(\"africa-network-comparison-osm.pdf\", bbox_inches='tight')" ] }, { @@ -530,7 +532,7 @@ "import contextily as cx # Need to be installed `pip3 install contextily`\n", "\n", "# adapt all sizes\n", - "size = 1\n", + "size = 0.5\n", "# Create the basemap that is called by ax\n", "ax = africa_shape.to_crs(epsg=\"3857\").plot(\n", " figsize=(20 * size, 20 * size), alpha=0.5, facecolor=\"white\", edgecolor=\"whitesmoke\"\n", @@ -584,7 +586,9 @@ "# ticks & edge modification of cbar\n", "cbar.ax.yaxis.set_tick_params(color=\"grey\")\n", "plt.setp(plt.getp(cbar.ax.axes, \"yticklabels\"), color=\"dimgrey\")\n", - "cbar.outline.set_edgecolor(None) # set colorbar edgecolor" + "cbar.outline.set_edgecolor(None) # set colorbar edgecolor\n", + "\n", + "# plt.savefig(\"africa-network-comparison-worldbank.pdf\", bbox_inches='tight')" ] }, { @@ -653,7 +657,9 @@ " 1, label=\"330kV\", color=blues(normalized_voltage.unique()[1] + 0.1), linewidth=5\n", ")\n", "plt.rc(\"legend\", fontsize=15)\n", - "ax.legend()" + "ax.legend()\n", + "\n", + "# plt.savefig(\"nigeria-network-comparison-osm.pdf\", bbox_inches='tight')" ] }, { @@ -720,7 +726,9 @@ " 1, label=\"330kV\", color=reds(normalized_voltage.unique()[1] + 0.1), linewidth=5\n", ")\n", "plt.rc(\"legend\", fontsize=15)\n", - "ax.legend()" + "ax.legend()\n", + "\n", + "# plt.savefig(\"nigeria-network-comparison-worldbank.pdf\", bbox_inches='tight')" ] } ],