{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Electrify_Clusters" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### All the necessary Python imports" ] }, { "cell_type": "code", "execution_count": 2, "metadata": {}, "outputs": [], "source": [ "%matplotlib inline\n", "from pathlib import Path\n", "\n", "from electrificationplanner import clustering, electrify\n", "\n", "import sys\n", "sys.path.insert(0, '../minigrid-optimiser')\n", "from mgo import mgo" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### If clusters not already created, create it now" ] }, { "cell_type": "code", "execution_count": null, "metadata": {}, "outputs": [], "source": [ "folder_input = Path('/home/chris/Documents/GIS')\n", "ghs_in = folder_input / 'GHS-POP/GHS_POP_GPW42015_GLOBE_R2015A_54009_250_v1_0.tif'\n", "clip_boundary = folder_input / 'gadm_uganda.gpkg'\n", "clip_boundary_layer = 'gadm36_UGA_0'\n", "grid_in = folder_input / 'uganda_grid.gpkg'\n", "clusters_file = folder_input / 'clusters.gpkg'\n", "\n", "print('Clipping raster...', end='', flush=True)\n", "clipped, affine, crs = clustering.clip_raster(ghs_in, clip_boundary, clip_boundary_layer)\n", "print('\\t\\tDoneCreating clusters...', end='', flush=True)\n", "clusters = clustering.create_clusters(clipped, affine, crs)\n", "print('\\t\\tDoneFiltering and merging...', end='', flush=True)\n", "clusters = clustering.filter_merge_clusters(clusters)\n", "print('\\tDone\\nGetting population...', end='', flush=True)\n", "clusters = clustering.cluster_pops(clusters, ghs_in)\n", "print('\\t\\tDoneGetting grid dists...', end='', flush=True)\n", "clusters = clustering.cluster_grid_distance(clusters, grid_in, clipped[0].shape, affine)\n", "print(f'\\t\\tDoneSaving to {str(clusters_out)}...', end='', flush=True)\n", "clustering.save_clusters(clusters, clusters_file)\n", "print('\\t\\tDone')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Enter all input data here" ] }, { "cell_type": "code", "execution_count": 3, "metadata": {}, "outputs": [], "source": [ "folder_input = Path('/home/chris/Documents/GIS')\n", "\n", "clusters_file = folder_input / 'clusters.gpkg' # must be polygons with attributes pop_sum, area_m2, grid_dist\n", "clusters_out = folder_input / 'clusters_out1.gpkg'\n", "network_out = folder_input / 'network_out1.gpkg'\n", "\n", "grid_dist_connected = 1000 # clusters within this distance of grid are considered connected\n", "\n", "minimum_pop = 500 # exclude any population below this\n", "\n", "# off-grid costs\n", "demand_per_person_kwh_month = 6 # 6kWh/month = MTF Tier 2\n", "demand_per_person_kw_peak = demand_per_person_kwh_month / (4*30) # 130 4hours/day*30days/month based on MTF numbers, should use a real demand curve\n", "mg_gen_cost_per_kw = 4000\n", "mg_cost_per_m2 = 2\n", "\n", "# grid costs\n", "cost_wire_per_m = 50\n", "grid_cost_per_m2 = 2" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Read in the clusters file, convert to desired CRS (ostensibly better for distances) and convert to points, filter on population along the way" ] }, { "cell_type": "code", "execution_count": 8, "metadata": {}, "outputs": [], "source": [ "clusters = electrify.load_clusters(clusters_file, grid_dist_connected=grid_dist_connected,\n", " minimum_pop=minimum_pop)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### We then take all the clusters and calculate the optimum network that connects them all together. The ML model returns T_x and T_y containing the start and end points of each new arc created" ] }, { "cell_type": "code", "execution_count": 9, "metadata": {}, "outputs": [], "source": [ "network, nodes = electrify.create_network(clusters)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Then we're ready to calculate the optimum grid extension.\n", "This is done by expanding out from each already connected node, finding the optimum connection of nearby nodes. This is then compared to the off-grid cost and if better, these nodes are marked as connected. Then the loop continues until no new connections are found." ] }, { "cell_type": "code", "execution_count": 12, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "650\n", "412\n", "227\n", "98\n", "29\n", "5\n", "2\n", "1\n" ] } ], "source": [ "network, nodes = electrify.run_model(network,\n", " nodes,\n", " demand_per_person_kw_peak=demand_per_person_kw_peak,\n", " mg_gen_cost_per_kw=mg_gen_cost_per_kw,\n", " mg_cost_per_m2=mg_cost_per_m2,\n", " cost_wire_per_m=cost_wire_per_m,\n", " grid_cost_per_m2=grid_cost_per_m2)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### And then do a join to get the results back into a polygon shapefile" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "network_gdf, clusters_joined = electrify.spatialise(network, nodes, clusters)" ] }, { "cell_type": "code", "execution_count": null, "metadata": { "scrolled": true }, "outputs": [], "source": [ "clusters_joined.to_file(str(clusters_out), driver='GPKG')\n", "network_gdf.to_file(str(network_out), driver='GPKG')" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### And display some summary results" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "2686 connected\n", "263 off-grid\n", "2686 lines\n", "\n", "Cost $4,445,207,706\n", "\n", "Modelled pop: 37,326,380\n", "Currently electrified: 15,139,688\n", "New connections: 11,867,482\n", "Off-grid connections 226,084\n" ] } ], "source": [ "new_conns = clusters_joined.loc[clusters_joined['conn_end'] == 1].loc[clusters_joined['conn_start'] == 0]\n", "og = clusters_joined.loc[clusters_joined['conn_end'] == 0]\n", "arcs = network_gdf.loc[network_gdf['existing'] == 0].loc[network_gdf['enabled'] == 1]\n", "cost = og['og_cost'].sum() + cost_wire_per_m * arcs['length'].sum() + grid_cost_per_m2 * new_conns['area_m2'].sum()\n", "\n", "total_modelled_pop = clusters['pop_sum'].sum()\n", "urban_elec_rate = 0.6\n", "currently_electrified = clusters.loc[clusters['conn_start'] == 1, 'pop_sum'].sum() * urban_elec_rate\n", "new_conn_pop = clusters_joined.loc[clusters_joined['conn_start'] == 0].loc[clusters_joined['conn_end'] == 1, 'pop_sum'].sum()\n", "off_grid_pop = clusters_joined.loc[clusters_joined['conn_start'] == 0].loc[clusters_joined['conn_end'] == 0, 'pop_sum'].sum()\n", "\n", "print(f'{len(new_conns)} connected')\n", "print(f'{len(og)} off-grid')\n", "print(f'{len(arcs)} lines')\n", "print()\n", "print(f'Cost ${cost:,.0f}')\n", "print()\n", "print(f'Modelled pop: {total_modelled_pop:,.0f}')\n", "print(f'Currently electrified: {currently_electrified:,.0f}')\n", "print(f'New connections: {new_conn_pop:,.0f}')\n", "print(f'Off-grid connections {off_grid_pop:,.0f}')" ] } ], "metadata": { "kernelspec": { "display_name": "Python 3", "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.6.4" } }, "nbformat": 4, "nbformat_minor": 2 }