import folium
import pandas as pd
import numpy as np
import geopandas as gpd
import json
import os
import osmnx as ox
import eefolium
import ee
import geemap.foliumap as geemap
from folium import plugins, CustomIcon, Html
import geopandas as gpd
import matplotlib.pyplot as plt
import os
import json
import nbconvert
import datetime as dt
import numpy as np
from branca.colormap import linear
import hvplot
import hvplot.pandas
import holoviews as hv
# This will add the .hvplot() function to your DataFrame!
import hvplot.pandas
import holoviews as hv
hv.extension('bokeh')
city = 'Luanda'
os.chdir('C:/Users/jtrum/Wash scan/data/')
aoi = gpd.read_file('aoiLuanda.geojson')
defecation = gpd.read_file('ihme_defecation_aoi.geojson')
defecation['idx'] = defecation.index + 1
sanitation = gpd.read_file('ihme_sanitation_aoi.geojson')
sanitation['idx'] = sanitation.index + 1
water = gpd.read_file('ihme_water_aoi.geojson')
water['idx'] = water.index + 1
hex = gpd.read_file('hdsl_hex.geojson')
schools = gpd.read_file('schools.geojson')
schools['idx'] = schools.index + 1
hospital = gpd.read_file('hospitals.geojson')
hospital['idx'] = hospital.index + 1
wsf = gpd.read_file('wsf.geojson')
imp = gpd.read_file('imperviousness.geojson')
imp['idx'] = 'Impervious'
lakes = gpd.read_file('lakes.geojson')
lakes['Feature'] = 'Lake'
basin = gpd.read_file('basin.geojson')
basin['Feature'] = 'Basin'
rivers = gpd.read_file('rivers.geojson')
rivers['Feature'] = 'River'
FU_1pct = gpd.read_file('FU_1pct.geojson')
FU_1to10pct = gpd.read_file('FU_1to10pct.geojson')
FU_10pct = gpd.read_file('FU_10pct.geojson')
P_1pct = gpd.read_file('P_1pct.geojson')
P_1to10pct = gpd.read_file('P_1to10pct.geojson')
P_10pct = gpd.read_file('P_10pct.geojson')
w_inf = gpd.read_file('water_infrastructure.geojson')
cat = gpd.read_file('luanda_catchment_level4.shp').to_crs('EPSG:4326')
# dams = gpd.read_file(f'{city.lower()}_dams.shp').to_crs('EPSG:4326')
# reservoirs = gpd.read_file(f'{city.lower()}_reservoirs.shp').to_crs('EPSG:4326')
# dams['DAM_ID'] = dams['DAM_ID'].astype('int').astype('str')
# precip = pd.read_csv('precip.csv')
# precip['time'] = pd.to_datetime(precip['time'])
Luanda, Angola, the largest and capital city of the country, situated on the northern Atlantic coast, serves as a pivotal seaport for both Angola and the broader Atlantic coast of Africa. Since its establishment by Portuguese settlers in 1576, Luanda has encountered numerous challenges in maintaining adequate water and sanitation infrastructure, exacerbated by historical factors, rapid population growth, inequitable governance, and dated infrastructure.
The city's trajectory was significantly impacted by the civil war following Angola's independence in 1975, lasting until 2002, which resulted in widespread insecurity and infrastructural damage. The post-war population surge further strained existing resources, amplifying the difficulties in providing reliable water sources, sewage treatment, and waste management services. Moreover, the rapid post-war urbanization contributed to the increase of informal settlements, known as mussques, which around 80% of the population live in. As these peri-urban communities became more prominent, they relied on informal mechanisms for water supply, thus water extraction, transportation, and retailing became the largest sub-sector of Luanda's extensive informal economy. While this ultimately manifested in lack of water governance, it created an opportunity to improve community-level management to manage water challenges.
Luanda's top-down governance of public utility services, limited institutional capacity, insufficient financial resources, and its infromalized economy are constraints that have impeded the city's efforts to reverse its decades-long decline in access to reliable water and sanitation sources. Recent interest from both private and public entities have helped create funding opportunities to modernize and expand infrastructure. Even in the last three years, funding for basic sanitation grew throughout Angola, and Luanda has one of the most advanced systems despite only having an operable wastewater system. Some of the main barriers to growth are a lack of nexus connecting priorities, investment, and funding sources, a lack of bids for long-term investment and strategic planning for financing in the WASH sector, and too much institutional power that prohibits streamlined project implementation. However, with the substantial resources at its disposal, Luanda possesses significant potential to enhance the accessibility and reliability of its water and sanitation infrastructure.
In Luanda, fundamental hygienic practices and infrastructure face significant barriers. While recent investments have focused on connecting residents to piped water networks and expanding sanitation infrastructure in urban communities, challenges persist. Despite these efforts, Angolans continue to grapple with high rates of vectorborne and waterborne illnesses, malnutrition, malaria, and child mortality. As of 2021, Angola's Human Capital Index is 0.36, one of the lowest scores in sub-Saharan Africa. This underscores the urgent need for continued investment and improvement in healthcare and basic services. Of particular concern is the disproportionate burden borne by women and children in the collection and distribution of water. This places these vulnerable populations at the greatest risk of suffering the adverse effects of unhygienic practices. Addressing these challenges requires a multifaceted approach, combining infrastructure development, public health initiatives, and targeted support for marginalized communities.
The research highlights significant challenges and initiatives in water, sanitation, and hygiene (WASH) in Angola. Despite abundant water resources, accessibility and potability remain minimal, contributing to below-average health outcomes compared to other countries in sub-Saharan Africa. Waterborne illnesses, affecting maternal and child health, are prevalent due to poor infrastructure and formal water management. The Angolan government is actively investing in water resources and infrastructure, particularly focusing on the urbanizing population.
Recent projects, including a 2017 World Bank loan and the Luanda 2nd Bita Water supply project, aim to connect over 950,000 people to clean water through new pipe networks. However, infrastructure built in the 1970s for approximately 500,000 people struggles to keep pace with Luanda's rapid urban growth. The country's civil war exacerbated these challenges, with the sale of water becoming a significant informal economy sector, highlighting the deficiencies in formal water management.
In terms of sanitation, urbanized areas face the greatest challenges in accessing improved facilities. Efforts are underway to execute interceptor projects, expanding wastewater collection and enhancing coastal cleanliness. Despite these efforts, 55% of Angolan households lack adequate sanitation facilities, and 68% of schools lack handwashing facilities on-site, underscoring governance issues in maintenance and infrastructure.
Hygiene interventions, such as those by UNICEF in 2021, aim to promote infection prevention and control in institutions and communities in Luanda. However, high rates of malaria and intestinal infections persist among children under the age of one, contributing to Angola's high child mortality rate in SS-Afr. Additionally, limited access to health services results in 50% of women giving birth at home, and only 28% of children receive measles vaccination or protection, further exacerbating health challenges.
This water and sanitation scan is divided in the following sections.
Section 1: Geography
Section 2: Water Related Hazards
Section 3: Service Delivery
Section 4: Sanitation
Section 5: Summary
Luanda is a city on the southwest coasst of Africa and has an incredibly diverse geography and climate. It experiences a tropical savanna climate with distinctive wet and dry seasons, often characterized by high temperatures and humidity year round. Moreover, Angola has a diverse array of biomes and eco-climates, making it the second most climactically diverse country in southern Africa, second to South Africa. With a robust network of groundwater and surface water resources, and a varying land cover of predominantly grasslands and urbanization, Luanda has experienced a rapidly changing landscape, with ramifications ranging from increased erosion, intense rain episodes, and extensive floodplains.
This map uses the Hydro ATLAS data suite to observe hydrogaphic features in Luanda, namely, basins, rivers and lakes.
Luanda has a robust surface water network, and Angola has a robust groundwater network. Angola has 47 major river basins and rivers spanning across 5 principal drainage areas while also sharing five international river basins. It is a predominantly upstream state.
m1 = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=9, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m1)
# add basin
b = folium.GeoJson(basin,
name='Basins',
style_function=lambda x: {'color': 'lightgrey',
'fillColor': 'lightgrey',
'weight': 1,
'fillOpacity': 0.3
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Feature']),
).add_to(m1)
# add rivers
r = folium.GeoJson(rivers,
name='Rivers',
style_function=lambda x: {'color': '#05e0f4',
'weight': 3,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Feature', 'LENGTH_KM', 'DIST_DN_KM', 'DIST_UP_KM', 'CATCH_SKM'],
aliases=['Feature', 'Length (km)', 'Downstream distance (km)', 'Upstream distance (km)', 'Catchment area (km2)'])
).add_to(m1)
# add lakes
l = folium.GeoJson(lakes,
name='Lakes',
style_function=lambda x: {'color': '#007ba7',
'weight': 3,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Feature', 'Lake_area', 'Depth_avg', 'Dis_avg'],
aliases=['Feature', 'Area (km2)', 'Average depth (m)', 'Average discharge (m3/s)'])
).add_to(m1)
# add a layer control
folium.LayerControl(collapsed=False, overlay=True).add_to(m1)
# add a legend for the basin, rivers, and lakes
legend_html = '''
<div style="position: fixed;
bottom: 450px; right: 10px; width: 150px; height: 75px;
border:2px solid grey; z-index:9999; font-size:12px; background-color:white;
"> <b>Hydrologic Feature</b> <br>
<i class="fa fa-square fa-1.5x" style="color:lightgrey"></i> Basin<br>
<i class="fa fa-square fa-1.5x" style="color:#05e0f4"></i> River<br>
<i class="fa fa-square fa-1.5x" style="color:#007ba7"></i> Lake
</div>
'''
m1.get_root().html.add_child(folium.Element(legend_html))
m1.keep_in_front(b)
m1.keep_in_front(r)
m1.keep_in_front(l)
m1
This map uses the GOODD and GRAND data suites to visualize reservoirs and dams in Luanda.
Built in the 1950s, the Cambambe Dam is one of Angola's oldest hydropower facilities. It underwent significant rehabilitation and expansion in recent years to increase its capacity. The dam provides hydroelectric power to Luanda and other nearby areas. Its reservoir, Lake Cambambe, serves as a source of water for various purposes, including irrigation and industrial use. The Capanda Dam and Lauca Dam are also recent dam projects nearby to Luanda predominantly for electricity generation.
dams = gpd.read_file(f'{city.lower()}_dams.shp')
reservoirs = gpd.read_file(f'{city.lower()}_reservoirs.shp')
cat = gpd.read_file('luanda_catchment_level4.shp').to_crs('EPSG:4326')
# Create a folium map centered on the AOI
mymap = folium.Map(tiles="Cartodb Positron", control_scale = True, zoom_control=False)
bounds = cat.total_bounds.tolist()
mymap.fit_bounds([bounds[:2][::-1], bounds[2:][::-1]])
folium.GeoJson(
cat,
style_function=lambda feature: {
'fillColor': 'transparent',
'color': 'gray',
'weight': 3
},).add_to(mymap)
res_tooltip = folium.GeoJsonTooltip(fields=['RES_NAME'], aliases=['Reservoir Name'], localize=True, style=('background-color: white; color: #333333;'))
dam_tooltip = folium.GeoJsonTooltip(fields=['DAM_ID'], aliases=['Dam ID'], localize=True, style=('background-color: white; color: #333333;'))
# Add blue polygons for reservoirs
folium.GeoJson(
reservoirs,
style_function=lambda feature: {
'fillColor': 'blue',
'color': 'blue',
'weight': 1,
},
highlight_function=lambda x: {"fillOpacity": 0.7},
tooltip=res_tooltip,
zoom_on_click=True
).add_to(mymap)
# Add CircleMarkers for dams
folium.GeoJson(
dams,
name="Dams",
marker=folium.CircleMarker(radius=8, fill_color="brown", fill_opacity=0.4, color="brown", weight=1),
tooltip = dam_tooltip,
highlight_function=lambda x: {"fillOpacity": 0.7},
zoom_on_click=True,
).add_to(mymap)
# Add legend manually
legend_html = '''
<div style="position: fixed;
bottom: 50px; left: 50px; width: 150px; height: 70px;
background-color: white; border:2px solid grey; z-index:9999; font-size:14px;
"> <b>Legend</b> <br>
Reservoirs
<svg height="15" width="15">
<rect width="15" height="15" style="fill:blue;stroke:blue;stroke-width:2;fill-opacity:0.5" />
</svg><br>
Dams
<svg height="10" width="10">
<circle cx="5" cy="5" r="5" style="fill:brown;stroke:brown;stroke-width:2;fill-opacity:0.5" />
</svg>
</div>
'''
mymap.get_root().html.add_child(folium.Element(legend_html))
mymap
Using Google Earth Engine, this map visualises land cover. Land cover data is from the European Space Agency (2021) and is a 10 meter resolution. Land cover is divided into 11 classes.
Land cover across Luanda is predominantly grasslands and built-up urbanization. With the boom in population during and post-civil war, the city continued to expand outward, both in terms of disorganized rural settlements and satellite towns, with nearly 1 million homes on a total of 100,000 hectares used. Another major urban expansion in 2011 resulted in 7 municipalities across the city. Angola has a diverse landscape, with the northern part of the country predominantly being tropical rainforests, and savanna deserts to the south. Luanda is a part of the Angolan scarp, a strip of savannah and woodlands, which causes high humidity and summer rains, endemic wildlife, and a mixture of forest, grasslands, and mangroves.
# load data
#landcover = gpd.read_file('land_cover.shp')
import rasterio as rio
import matplotlib.pyplot as plt
lc_raster = rio.open('C:/Users/jtrum/Wash scan/rasters/luanda_lc.tif')
# read raster data
raster_data = lc_raster.read(1) # assuming you want to plot the first band
# Define categories and corresponding numerical values
categories = ['No Data', 'Tree Cover', 'Shrub Cover', 'Grassland', 'Cropland', 'Built-Up', 'Sparse Vegetation', 'Snow and Ice', 'Permanent Water Bodies', 'Wetlands', 'Mangroves', 'Moss and Lichen']
values = [0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 95, 100]
# Define colors for each category
colors = ['white', '#006400', '#FFBB22', '#FFFF4C', '#F096FF', '#FA0000', '#FA0000', '#F0F0F0', '#0064C8', '#0096A0', '#00CF75', '#FAE6A0']
# Create a colormap
cmap = ListedColormap(colors)
# plot raster
plt.figure(figsize=(10, 10))
plt.imshow(raster_data, cmap=cmap)
legend_items = [
{'color': 'white', 'category': 'No Data'},
{'color': '#006400', 'category': 'Tree Cover'},
{'color': '#FFBB22', 'category': 'Shrub Cover'},
{'color': '#FFFF4C', 'category': 'Grassland'},
{'color': '#F096FF', 'category': 'Cropland'},
{'color': '#FA0000', 'category': 'Built-Up'},
{'color': '#B4B4B4', 'category': 'Sparse Vegetation'},
{'color': '#F0F0F0', 'category': 'Snow and Ice'},
{'color': '#0064C8', 'category': 'Permanent Water Bodies'},
{'color': '#0096A0', 'category': 'Wetlands'},
{'color': '#00CF75', 'category': 'Mangroves'},
{'color': '#FAE6A0', 'category': 'Moss and Lichen'}
]
plt.title('Luanda Land Cover')
plt.show()
import seaborn as sns
lc_csv = pd.read_csv('Luanda_LC.csv')
lc = lc_csv.copy()
color_codes = ['#006400', '#FFBB22', '#FFFF4C', '#F096FF', '#FA0000', '#B4B4B4', '#F0F0F0', '#0064C8', '#0096A0', '#00CF75', '#FAE6A0']
land_cover_categories = ['Trees', 'Shrublands', 'Grasslands', 'Croplands', 'Built-Up', 'Barren', 'Snow and Ice', 'Water Bodies', 'Herbaceous Wetlands', 'Mangroves', 'Moss and Lichen']
# Zip land cover categories with their respective colors into a dictionary
color_dict = dict(zip(land_cover_categories, color_codes))
# Assuming 'lc' is your DataFrame with columns 'percentage' and 'cover'
lc = lc.sort_values(by=['percentage'], ascending=False)
sns.set_style("white")
fig, ax = plt.subplots(figsize=(12, 6))
# Add percentage to be just right of the bar, rounded to 2 decimal places
for index, row in lc.iterrows():
ax.text(row.percentage + 0.2, row.cover, str(round(row.percentage, 2)), color='black', ha="left", va='center', fontsize=12)
# Create a custom color palette using the color_dict
custom_palette = [color_dict[cover] for cover in lc['cover']]
# Use the custom_palette for the barplot
ax = sns.barplot(x="percentage", y="cover", data=lc, palette=custom_palette)
ax.set(xlabel="Percentage (%)", ylabel="Category")
ax.set_title('Land Cover by % (Luanda, Angola)', fontsize=16)
plt.show()
# # Replacing sns.barplot with hvplot.bar
# bar_plot = lc.hvplot.bar(
# y='cover', x='percentage', stacked=False,
# rot=0, height=400, width=700,
# title='Land Cover by % (Luanda, Angola)',
# xlabel='Percentage (%)', ylabel='Category',
# color='cover', legend=False,
# hover_color='black', cmap=color_dict,
# fontsize=dict(title=16, labels=12),
# ).opts(toolbar=None)
# bar_plot
This line plot visualizes monthly rainfall in millimeters for every month between 1993 and 2022.
Precipitation in Luanda is often quite sparse. The rainiest months tend to be March and April, with the driest months being immediately after from May to October. Although rain events are infrequent, they are often intense. In 2023, consecutive days of heavy rainfall destroyed nearly 20,000 homes around Luanda.
precip = pd.read_csv('precip.csv')
precip['time'] = pd.to_datetime(precip['time'])
# change column names
precip.columns = ['Date', 'Precipitation (mm)']
# create new column called 'Month'
precip['Month'] = precip['Date'].dt.month
# get an average of precipitation for each month
monthly_precip = precip.groupby('Month').mean()
# reset index
monthly_precip = monthly_precip.reset_index().drop(columns='Date')
# change month number to month name
monthly_precip['Month'] = monthly_precip['Month'].apply(lambda x: dt.date(1900, x, 1).strftime('%B'))
# plot
# Create the line chart using Seaborn with connected lines
# plt.figure(figsize=(12, 6))
# sns.set_style("white")
# sns.lineplot(data=precip, x='time', y='precip', linewidth=1, color = '#2b8cbe')
# # sns.lineplot(data=df, x='time', y=df.precip.mean(), linewidth=1, color = 'grey')
# # Add labels and title
# plt.xlabel('')
# plt.ylabel('')
# plt.title('Monthly precipitation 1993-2022 (mm)')
# # plt.xticks(rotation=45)
# plt.grid(False)
# plt.show()
precip.hvplot.line(
x='Date',
y='Precipitation (mm)',
line_width=2.5,
width=800,
height=400,
legend='top_left',
title='Monthly precipitation 1993-2022 (mm)',
color='#6fa8dc',
xlabel='Year',
ylabel='')
# make a bar chart of the monthly precipitation using hv plot
monthly_precip.hvplot.bar(
x='Month',
y='Precipitation (mm)',
rot=45,
width=800,
height=400,
title='Average Monthly Precipitation (mm)',
xlabel='Month',
ylabel='Precipitation (mm)',
color='#6fa8dc',
hover_color='black',
cmap='viridis',
fontsize=dict(title=16, labels=12),
).opts(toolbar=None)
This map visualizes both net runoff and fast surface and subsurface runoff.
The water distribution capacity in Luanda is currently at 30 percent, falling significantly short of requirements. Furthermore, the basic sanitation infrastructure covers only 3 percent of the city's population, indicating a minimal provision for drainage ditches intended to manage water runoff. Issues surrounding runoff likely stem from rapid urbanization, poor drainage infrastructure, and prominence of informal settlements.
import folium
from branca.colormap import linear
import geopandas as gpd
import pandas as pd
var_list = {'ncrun': 'Net cell runoff',
'qs': 'Fast surface and fast subsurface runoff'}
stat_list = {'mean': 'mean',
'std': 'standard deviation'}
year_list = range(1987, 2017)
# Assuming var_list, stat_list, and city are defined earlier in your code
# Create the folium map
mymap = folium.Map(tiles="Cartodb Positron", control_scale=True, zoom_control=False)
aoi_bounds = cat.total_bounds.tolist()
mymap.fit_bounds([aoi_bounds[:2][::-1], aoi_bounds[2:][::-1]])
folium.GeoJson(
cat,
style_function=lambda feature: {
'fillColor': 'transparent',
'color': 'gray',
'weight': 3
},
control=False).add_to(mymap)
for var in var_list:
for stat in stat_list:
# Read the GeoJSON file
json = gpd.read_file(f'{city.lower()}_{var}_{stat}.geojson').to_crs('epsg:4326')
# Set colormap
if var == 'ncrun':
colormap = linear.GnBu_09.scale(json['raster_val'].min(), json['raster_val'].max())
elif var == 'qs':
colormap = linear.YlGnBu_09.scale(json['raster_val'].min(), json['raster_val'].max())
colormap.caption = f"{var_list[var]} ({stat_list[stat]}) (mean / standard deviation)"
colormap.add_to(mymap)
# Add GeoJson layer with choropleth style
folium.GeoJson(
json,
name=f'{var_list[var]} ({stat_list[stat]})',
style_function=lambda feature: {
'fillColor': 'transparent' if pd.isna(feature['properties']['raster_val']) else colormap(feature['properties']['raster_val']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['raster_val'], aliases=[f'{var_list[var]} ({stat_list[stat]})'],
labels=True, sticky=False),
show=(var == 'ncrun' and stat == 'mean') # Show by default only if it's the 'ncrun' mean
).add_to(mymap)
# Add Layer Control to toggle the choropleth layer
folium.LayerControl().add_to(mymap)
mymap
Luanda experiences a notably high rate of evapotranspiration, leading to prolonged and frequent drought events, particularly in regions with extensive agricultural activity. The city's extended dry seasons, often outweighing the shorter wet seasons, significantly impact agricultural productivity. With only approximately 3% of Luanda's agricultural land being irrigated, coupled with the presence of aquifer systems in Angola, evapotranspiration exacerbates meteorological concerns, posing substantial challenges to water availability and agricultural sustainability in the region.
df = pd.read_csv('potential_evaporation.csv')
# convert time column from datetime to just date
df['time'] = pd.to_datetime(df['time']).dt.date
# rename Ep column to Evaporation
df.rename(columns={'Ep': 'Evaporation', 'time': 'Date'}, inplace=True)
df.hvplot.line(
x='Date',
y='Evaporation',
line_width=2.5,
width=800,
height=400,
legend='top_left',
title='Monthly Potential Evaporation (mm/day) from 2003 to 2022',
color='#c51b8a',
xlabel='Year',
ylabel='')
In Angola, rainfall can be sporadic, but when it does occur, it often comes in intense precipitation events that lead to significant loss of life and property, particularly due to flooding. Despite these challenges, only half of the country's population has access to clean drinking water, contributing to one of the highest rates of waterborne diseases in Africa. This combination of limited access to potable water and frequent water-related hazards underscores the urgent need for improved water infrastructure and disaster preparedness measures across the country.
Luanda's rainy season spanning from October to May. Recent years have witnessed the city's susceptibility to flooding, with notable instances of devastation. In 2023, heavy rainfall over successive days led to the destruction of numerous homes in Luanda Providence, while 2021 saw over 11,000 individuals affected, 2,300 homes damaged, and 24 lives lost due to flooding. Despite infrequent rainfall throughout the season, its intensity presents significant risks, notably for the approximately 30 percent of Angola residents residing within 100 kilometers of the coastline, a demographic trend further exacerbated by urban migration. River inundation poses a pervasive threat across mainland areas, with coastal regions experiencing a heightened vulnerability to flooding. These at-risk locales often coincide with the city's agricultural lands, exacerbating the socio-economic repercussions of flooding on local farming communities. The imperative to fortify Luanda against flooding is paramount, not solely to safeguard its inhabitants but also due to its pivotal role as a major port city in Africa's blue economy. Given that an estimated 90 percent of the continent's import and export trade transits through coastal ports, enhancing resilience against flooding assumes critical importance for sustaining economic activities and ensuring the city's enduring prosperity.
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m)
# add FU_1pct to map as #90e0ef
f1 = folium.GeoJson(FU_1pct,
name='Fluvial Undefended (1% AEP)',
style_function=lambda x: {'color': '#05e0f4',
'fillColor': '#05e0f4',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=True
).add_to(m)
# add FU_1to10pct to map as #00b4d8
f2 = folium.GeoJson(FU_1to10pct,
name='Fluvial Undefended (1-10% AEP)',
style_function=lambda x: {'color': '#03a0ae',
'fillColor': '#03a0ae',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# add FU_10pct to map as #0077b6
f3 = folium.GeoJson(FU_10pct,
name='Fluvial Undefended (10% AEP)',
style_function=lambda x: {'color': '#026068',
'fillColor': '#026068',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# add P_1pct to map as #16f5d3
p1 = folium.GeoJson(P_1pct,
name='Pluvial (1% AEP)',
style_function=lambda x: {'color': '#29d0ca',
'fillColor': '#29d0ca',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=True
).add_to(m)
# add P_1to10pct to map as #29ccc7
p2 = folium.GeoJson(P_1to10pct,
name='Pluvial (1-10% AEP)',
style_function=lambda x: {'color': '#1d9490',
'fillColor': '#1d9490',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# add P_10pct to map as #04a6b5
p3 = folium.GeoJson(P_10pct,
name='Pluvial (10% AEP)',
style_function=lambda x: {'color': '#115956',
'fillColor': '#115956',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# legend
legend_html = '''
<div style="position: fixed;
bottom: 300px; right: 0px; width: 250px; height: 150px;
border:2px solid grey; z-index:9999; font-size:12px; background-color:white; color:black;
"> <b>Flood Scenario</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#90e0ef"></i> Fluvial Undefended (1% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#00b4d8"></i> Fluvial Undefended (1-10% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#0077b6"></i> Fluvial Undefended (10% AEP)<br>
<br>
<i class="fa fa-square fa-1.5x" style="color:#16f5d3"></i> Pluvial (1% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#29ccc7"></i> Pluvial (1-10% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#04a6b5"></i> Pluvial (10% AEP)<br>
</div>
'''
m.get_root().html.add_child(folium.Element(legend_html))
m.keep_in_front(f1)
m.keep_in_front(p1)
m.keep_in_front(f2)
m.keep_in_front(p2)
m.keep_in_front(f3)
m.keep_in_front(p3)
# add layer control
folium.LayerControl(collapsed=False,
overlay=True
).add_to(m)
m
The Standardized Precipitation Evapotranspiration Index (SPEI) provides insights into drought conditions by considering both precipitation and evapotranspiration. The data was extracted using SPEI Monitor by using 3 different time scales (1 month, 12 month, 48 month) at the centroid of Luanda. The range of values is -2.33 to 2.33, where greater, positive values indicate wet conditions, and smaller, negative values indicate dry conditions. The data was observed in between years 1993 to 2022.
The consistent pattern of smaller negative values across all time scales suggests a prevailing trend of slight precipitation deficits relative to potential evapotranspiration, indicating a tendency towards drier conditions over the analyzed period. Specifically, the 1-month SPEI values exhibit the most variability, indicating the influence of short-term weather patterns and seasonal fluctuations on precipitation and evapotranspiration dynamics. This variability likely reflects the sporadic nature of precipitation events, which may occur infrequently but intensively when they do happen.
spei = pd.read_csv('SPEI_-8.75_13.25.csv')
# in DATA column, make into string, turn the first 3 characters into month, and the last 4 into year
spei['Month'] = spei['DATA'].str[:3]
spei['Year'] = spei['DATA'].str[-4:]
# drop DATA column
spei = spei.drop(columns='DATA')
# only keep SPEI_1, SPEI_12, and SPEI_48 columns
spei = spei[['Month', 'Year', 'SPEI_1', 'SPEI_12', 'SPEI_48']]
# using Month and Year, make a column called Date, a datetime object
spei['Date'] = spei['Month'] + ' ' + spei['Year']
spei['Date'] = pd.to_datetime(spei['Date'], format='%b %Y')
# no day, just month and year
spei['Date'] = spei['Date'].dt.to_period('M')
# set year range
range = (1993, 2022)
# filter out years not in range
spei = spei[spei['Date'].dt.year.between(range[0], range[1])]
# drop Month and Year columns
spei = spei.drop(columns=['Month', 'Year'])
# reset index
spei = spei.reset_index(drop=True)
# change column names
spei.columns = ['SPEI (Short Term)', 'SPEI (Medium Term)', 'SPEI (Long Term)', 'Date']
spei
# print the average value for each SPEI value
print('Average Short Term SPEI: ' + str(round(spei['SPEI (Short Term)'].mean(), 2)))
print('Average Medium Term SPEI: ' + str(round(spei['SPEI (Medium Term)'].mean(), 2)))
print('Average Long Term SPEI: ' + str(round(spei['SPEI (Long Term)'].mean(), 2)))
# make a line plot of the SPEI values using hvplot, and different lines for each SPEI value
spei.hvplot.line(
x='Date',
y=['SPEI (Short Term)', 'SPEI (Medium Term)', 'SPEI (Long Term)'],
line_width=1.5,
width=800,
height=400,
legend='top_left',
title='SPEI Values for Luanda, Angola from 1993 to 2022',
xlabel='Year',
ylabel='SPEI Value',
color=['#c51b8a', '#4d9221', '#2b8cbe'],
hover_color='black',
cmap='viridis',
fontsize=dict(title=16, labels=12),
).opts(toolbar=None)
Average Short Term SPEI: -0.31 Average Medium Term SPEI: -0.11 Average Long Term SPEI: -0.18
Electrical Conductivity: While values remained stable from 1993 to 2002, there was a significant spike in electrical conductivity, indicating elevated levels of minerals potentially linked to runoff, industrial discharge, and wastewater. Between rapid urbanization and the end of the civil war, there may have been an increase in human-related minerals added to water.
Nitrate-Nitrite Levels: Monitoring nitrate and nitrite levels may indicate potential public health and environmental stressors. Highest monthly peaks are consistently in April, generally the wettest month of the year in Luanda.
Biological Oxygen Demand: With values generally below 2 mg/L, organic pollution in water sources are realtively low and are conducive to a healthy aquatic ecosystem.
ec = pd.read_csv(f'{city.lower()}_electrical_conductivity.csv')
noxn = pd.read_csv(f'{city.lower()}_nitrate_nitrite.csv')
bod = pd.read_csv(f'{city.lower()}_biological_oxygen_demand.csv')
ec['day'] = 1
ec['Date'] = pd.to_datetime(ec[['year', 'month', 'day']])
# change preds column to Electrical Conductivity (uS/cm)
ec = ec.rename(columns={'preds': 'Electrical Conductivity (uS/cm)'})
#ec.columns = ['Year', 'Month', 'Electrical Conductivity (uS/cm)', 'Day', 'Time']
noxn['day'] = 1
noxn['Date'] = pd.to_datetime(noxn[['year', 'month', 'day']])
noxn = noxn.rename(columns={'preds': 'Nitrate Nitrite (mg/L)'})
#noxn.columns = ['Year', 'Month', 'Nitrate Nitrite (mg/L)', 'Day', 'Time']
bod['day'] = 1
bod['Date'] = pd.to_datetime(bod[['year', 'month', 'day']])
bod = bod.rename(columns={'preds': 'Biological Oxygen Demand (mg/L)'})
#bod.columns = ['Year', 'Month', 'Biological Oxygen Demand (mg/L)', 'Day', 'Time']
# plot
# # Create the line chart using Seaborn with connected lines
# plt.figure(figsize=(12, 6))
# sns.lineplot(data=ec, x='time', y='preds', linewidth=1, color = '#e34a33')
# sns.set_style("white")
# # Add labels and title
# plt.xlabel('')
# plt.ylabel('')
# plt.title('Monthly electrical conductivity in surface water 1993-2022 (uS/cm)')
# # plt.xticks(rotation=45)
# plt.grid(False)
# plt.show()
ec.hvplot.line(
x='Date',
y='Electrical Conductivity (uS/cm)',
line_width=2.5,
color='#e34a33',
xlabel='',
ylabel='',
title='Monthly electrical conductivity in surface water 1993-2022 (uS/cm)',
grid=False)
# # plot
# # Create the line chart using Seaborn with connected lines
# plt.figure(figsize=(12, 6))
# sns.lineplot(data=noxn, x='time', y='preds', linewidth=1, color = '#016c59')
# sns.set_style("white")
# # Add labels and title
# plt.xlabel('')
# plt.ylabel('')
# plt.title('Monthly nitrate-nitrite in surface water 1993-2022 (mg/l)')
# # plt.xticks(rotation=45)
# plt.grid(False)
# plt.show()
noxn.hvplot.line(
x='Date',
y='Nitrate Nitrite (mg/L)',
line_width=2.5,
color='#016c59',
xlabel='',
ylabel='',
title='Monthly nitrate-nitrite in surface water 1993-2013 (mg/l)',
grid=False)
# # plot
# # Create the line chart using Seaborn with connected lines
# plt.figure(figsize=(12, 6))
# sns.lineplot(data=bod, x='time', y='preds', linewidth=1, color = '#1c9099')
# sns.set_style("white")
# # Add labels and title
# plt.xlabel('')
# plt.ylabel('')
# plt.title('Monthly biological oxygen demand in surface water 1993-2022 (mg/l)')
# # plt.xticks(rotation=45)
# plt.grid(False)
# plt.show()
bod.hvplot.line(
x='Date',
y='Biological Oxygen Demand (mg/L)',
line_width=2.5,
color='#1c9099',
xlabel='',
ylabel='',
title='Monthly biological oxygen demand in surface water 1993-2022 (mg/l)',
grid=False)
The current water and sanitation infrastructure in Luanda is notably sparse, posing a significant accessibility challenge, particularly for women and girls. Moreover, much of the existing water infrastructure in the city is aging, ill-suited for the current population size, and situated in flood-prone areas. These combined factors not only exacerbate the difficulty of accessing clean water but also increase the vulnerability of the population to environmental risks.
Water infrastructure in Luanda has been a chronic issue with reliable and accessible delivery of water resources. The infrastructure is aging and was designed for a pre-war population of nearly 500,000, but with Luanda's population approaching 2.7 million, it is not sustainable. With aging infrastructure, lack of maintenance, bureaucratic mismanagement, and the after impacts of water, Angola has made an increased commitment to rehabilitate existing systems, focusing predominantly in urban centers, for improvement and possible expansion.
Water Source: infrastructure involved in the collection, storage, and extraction of water from natural or artificial sources (eg. water well)
Water Distribution: infrastructure and systems responsible for delivering water from its source to consumers (eg. drinking water station)
Water Management: planning, operation, and maintenance of water-related infrastructure and resources (eg. storage tank)
m7 = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m7)
category_colors = {
'Water Source': '#86608e', # Change this to the color you want for source
'Water Distribution': '#ea879c', # Change this to the color you want for distribution
'Water Management': '#832322' # Change this to the color you want for management
}
#Plot water features, color by category
for cat in w_inf['Category'].unique():
folium.GeoJson(w_inf[w_inf['Category'] == cat],
name=cat,
style_function=lambda x, cat=cat: {
'color': category_colors[cat],
'fillColor': category_colors[cat],
'weight': 5,
'fillOpacity': 1,
# different shapes for different categories
'dashArray': '5, 5' if cat == 'Water Management' else '0, 0'
},
highlight_function=lambda x: {'weight': 2, 'fillOpacity': 1},
tooltip=folium.GeoJsonTooltip(fields=['Feature', 'Category'], aliases=['Feature', 'Category'], localize=True)
).add_to(m7)
# Add a layer control
folium.LayerControl(collapsed=False, overlay=True).add_to(m7)
# Add a legend for the water features
legend_html = '''
<div style="position: fixed;
bottom: 450px; right: 10px; width: 150px; height: 75px;
border:2px solid grey; z-index:9999; font-size:12px; background-color:white;
"> <b>Water Feature</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#86608e"></i> Water Source<br>
<i class="fa fa-square fa-1.5x" style="color:#ea879c"></i> Water Distribution<br>
<i class="fa fa-square fa-1.5x" style="color:#8e2322"></i> Water Management<br>
</div>
'''
m7.get_root().html.add_child(folium.Element(legend_html))
m7
This map combines the previous water infrastructure and flooding maps to understand if critical water infrastructure is within a flood zone. Pluvial flooding events pose a greater threat to water infrastructure. Considering the different water infrastructure types all play crucial roles in either the access, delivery, or maintenance of already limited water resources, the interesection of infrastructre and flood zones pose several negative implications including water contamination, srvice disruption, water quality degradation, financial costs, and operational challenges.
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m)
# add FU_1pct to map as #90e0ef
f1 = folium.GeoJson(FU_1pct,
name='Fluvial Undefended (1% AEP)',
style_function=lambda x: {'color': '#05e0f4',
'fillColor': '#05e0f4',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=True
).add_to(m)
# add FU_1to10pct to map as #00b4d8
f2 = folium.GeoJson(FU_1to10pct,
name='Fluvial Undefended (1-10% AEP)',
style_function=lambda x: {'color': '#03a0ae',
'fillColor': '#03a0ae',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# add FU_10pct to map as #0077b6
f3 = folium.GeoJson(FU_10pct,
name='Fluvial Undefended (10% AEP)',
style_function=lambda x: {'color': '#026068',
'fillColor': '#026068',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# add P_1pct to map as #16f5d3
p1 = folium.GeoJson(P_1pct,
name='Pluvial (1% AEP)',
style_function=lambda x: {'color': '#29d0ca',
'fillColor': '#29d0ca',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=True
).add_to(m)
# add P_1to10pct to map as #29ccc7
p2 = folium.GeoJson(P_1to10pct,
name='Pluvial (1-10% AEP)',
style_function=lambda x: {'color': '#1d9490',
'fillColor': '#1d9490',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
# add P_10pct to map as #04a6b5
p3 = folium.GeoJson(P_10pct,
name='Pluvial (10% AEP)',
style_function=lambda x: {'color': '#115956',
'fillColor': '#115956',
'weight': 1,
'fillOpacity': 0.7
},
highlight_function=lambda x: {'weight': 2,
'fillOpacity': 0.5
},
tooltip=folium.GeoJsonTooltip(fields=['Category', 'Return Period']),
show=False
).add_to(m)
#Plot water features, color by category
# add category colors
category_colors = {
'Water Source': '#86608e', # Change this to the color you want for source
'Water Distribution': '#ea879c',
'Water Management': '#8e2322'
}
for cat in w_inf['Category'].unique():
folium.GeoJson(w_inf[w_inf['Category'] == cat],
name=cat,
style_function=lambda x, cat=cat: {
'color': category_colors[cat],
'fillColor': category_colors[cat],
'weight': 5,
'fillOpacity': 1
},
highlight_function=lambda x: {'weight': 2, 'fillOpacity': 1},
tooltip=folium.GeoJsonTooltip(fields=['Feature', 'Category'], aliases=['Feature', 'Category'], localize=True, style=('background-color: black; color: white;') )
).add_to(m)
# legend
legend_html = '''
<div style="position: fixed;
bottom: 50px; right: 10px; width: 250px; height: 225px;
border:2px solid grey; z-index:9999; font-size:12px; background-color:white;
"> <b>Flood Scenario</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#90e0ef"></i> Fluvial Undefended (1% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#00b4d8"></i> Fluvial Undefended (1-10% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#0077b6"></i> Fluvial Undefended (10% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#16f5d3"></i> Pluvial (1% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#29ccc7"></i> Pluvial (1-10% AEP)<br>
<i class="fa fa-square fa-1.5x" style="color:#04a6b5"></i> Pluvial (10% AEP)<br>
<br>
<b>Water Feature</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#86608e"></i> Water Source<br>
<i class="fa fa-square fa-1.5x" style="color:#ea879c"></i> Water Distribution<br>
<i class="fa fa-square fa-1.5x" style="color:#8e2322"></i> Water Management<br>
</div>
'''
m.get_root().html.add_child(folium.Element(legend_html))
m.keep_in_front(f1)
m.keep_in_front(p1)
m.keep_in_front(f2)
m.keep_in_front(p2)
m.keep_in_front(f3)
m.keep_in_front(p3)
# add layer control
folium.LayerControl(collapsed=False, overlay=True).add_to(m)
# see any overlap between water infrastructure and flood scenarios
inf_total = len(w_inf)
P1_overlap = gpd.overlay(P_1pct, w_inf, how='intersection')
P2_overlap = gpd.overlay(P_1to10pct, w_inf, how='intersection')
P3_overlap = gpd.overlay(P_10pct, w_inf, how='intersection')
FU1_overlap = gpd.overlay(FU_1pct, w_inf, how='intersection')
FU2_overlap = gpd.overlay(FU_1to10pct, w_inf, how='intersection')
FU3_overlap = gpd.overlay(FU_10pct, w_inf, how='intersection')
# print how many water infrastructure features are in each flood scenario and the total / percent
print('There are a total of ' + str(inf_total) + ' water infrastructure features in ' + str(city) + ' and the overlap with each flood scenario is as follows:')
print('Pluvial (<1%): ' + str(len(P1_overlap)) + ' (' + str(round(len(P1_overlap)/inf_total*100, 2)) + '%)')
print('Pluvial (1-10%): ' + str(len(P2_overlap)) + ' (' + str(round(len(P2_overlap)/inf_total*100, 2)) + '%)')
print('Pluvial (10%): ' + str(len(P3_overlap)) + ' (' + str(round(len(P3_overlap)/inf_total*100, 2)) + '%)')
print('Fluvial (<1%): ' + str(len(FU1_overlap)) + ' (' + str(round(len(FU1_overlap)/inf_total*100, 2)) + '%)')
print('Fluvial (1-10%): ' + str(len(FU2_overlap)) + ' (' + str(round(len(FU2_overlap)/inf_total*100, 2)) + '%)')
print('Fluvial (10%): ' + str(len(FU3_overlap)) + ' (' + str(round(len(FU3_overlap)/inf_total*100, 2)) + '%)')
m
There are a total of 73 water infrastructure features in Luanda and the overlap with each flood scenario is as follows: Pluvial (<1%): 16 (21.92%) Pluvial (1-10%): 8 (10.96%) Pluvial (10%): 0 (0.0%) Fluvial (<1%): 3 (4.11%) Fluvial (1-10%): 2 (2.74%) Fluvial (10%): 0 (0.0%)
# make an interactive bar chart of the different intersection counts; use hvplot
# create a dataframe with the counts
overlap_df = pd.DataFrame({'Flood Scenario': ['Pluvial (<1%)', 'Pluvial (1-10%)', 'Pluvial (>10%)', 'Fluvial (<1%)', 'Fluvial (1-10%)', 'Fluvial (>10%)'],
'Water Infrastructure Overlap': [len(P1_overlap), len(P2_overlap), len(P3_overlap), len(FU1_overlap), len(FU2_overlap), len(FU3_overlap)]})
overlap_df['Percent'] = round(overlap_df['Water Infrastructure Overlap'] / inf_total * 100, 2)
overlap_df
# plot the bar chart, use colors from the flood scenario map
overlap_df.hvplot.bar(
x='Flood Scenario',
y='Percent',
rot=45,
width=800,
height=400,
title='Water Infrastructure Overlap with Flood Scenarios',
xlabel='Percent',
ylabel='Water Infrastructure Overlap',
color=['#16f5d3', '#29ccc7', '#04a6b5', '#90e0ef', '#00b4d8', '#0077b6'],
hover_color='black',
fontsize=dict(title=16, labels=12),
# set y maximum to 100% of total water infrastructure
ylim=(0, inf_total)
).opts(toolbar=None)
Angola, a country abundant in water resources, struggles with access to potable water, with only 52% of its population having reliable access. Efforts by organizations like USAID have supported programs targeting improved water and handwashing services, particularly in primary schools, where access is critical for reducing water-borne diseases and tackling absenteeism, notably among girls. However, many must access highlighted water in remote provinces like Pedreira, underscoring the infrastructure gaps and logistical hurdles in ensuring equitable access to clean water across Angola, even from Luanda. However, much of the core urbanized area has seen considerable increase in water accessibility as of 2017. Moreover, water is most expensive in the densest mussques, further higlighting the bureaucracy of water attainability.
# make a union of wsf polygons
wsf_union = gpd.GeoSeries(wsf.unary_union)
wsf_union = gpd.GeoDataFrame(wsf_union)
wsf_union.columns = ['geometry']
wsf_union.set_geometry('geometry', inplace=True)
wsf_union['idx'] = 'Built-Up'
# set crs of wsf_union to 4326
wsf_union.crs = {'init': 'epsg:4326'}
# Base map
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m)
# wsf geojson
wsf_geojson = folium.GeoJson(
wsf_union,
name='Built-Up Area (2015)',
style_function=lambda x: {'fillColor': 'black', 'color': 'black', 'weight': 0, 'fillOpacity': 0.6},
highlight_function=lambda x: {'weight': 0, 'color': 'black'},
tooltip=folium.features.GeoJsonTooltip(fields=['idx'], aliases=['Built-Up'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
# # water Choropleth
# water_choropleth = folium.Choropleth(
# data=water,
# geo_data=water,
# name='% Access to Improved Water Sources',
# columns=['idx', 'ID'],
# key_on='feature.properties.idx',
# fill_color='Blues',
# fill_opacity=0.7,
# line_opacity=0,
# legend_name='% Access to Improved Water Sources',
# highlight=True,
# bins=10,
# fixed_scale=True
# ).add_to(m)
# water_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(fields=['ID'],
# aliases=['% Access to Improved Water Sources'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap = linear.Blues_09.scale(water['ID'].min(), water['ID'].max())
colormap.caption = "% Access to Improved Water Sources"
colormap.add_to(m)
water_choro = folium.GeoJson(
water,
name='% Access to Improved Water Sources',
style_function=lambda feature: {
'fillColor': colormap(feature['properties']['ID']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['ID'], aliases = ['% Access to Improved Water Sources'], labels=True, sticky=False),
).add_to(m)
# Add schools and hospitals
sch = folium.GeoJson(
schools,
name='Schools',
style_function=lambda x: {'fillColor': '#ff00ff', 'color': '#ff00ff', 'weight': 0, 'fillOpacity': 1},
highlight_function=lambda x: {'weight': 0, 'color': '#ff00ff'},
tooltip=folium.features.GeoJsonTooltip(fields=['amenity'], aliases=['Schools'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
hos = folium.GeoJson(
hospital,
name='Hospitals',
style_function=lambda x: {'fillColor': 'yellow', 'color': 'yellow', 'weight': 0, 'fillOpacity': 1},
highlight_function=lambda x: {'weight': 0, 'color': 'yellow'},
tooltip=folium.features.GeoJsonTooltip(fields=['amenity'], aliases=['Hospitals'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
legend_html = '''
<div style="position: fixed;
bottom: 400px; right: 10px; width: 100px; height: 80px;
border:1px solid grey; z-index:9999; font-size:12px; background-color:white;
"> <b>Legend</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#black"></i> Built-Up Area<br>
<i class="fa fa-map-marker fa-1.5x" style="color:#ff00ff"></i> Schools<br>
<i class="fa fa-map-marker fa-1.5x" style="color:yellow"></i> Hospitals<br>
</div>
'''
# Add legend and CSS to map
m.get_root().html.add_child(folium.Element(legend_html))
# Add layer control
folium.LayerControl(collapsed=False, overlay=True).add_to(m)
# Organizing layers
m.keep_in_front(wsf_geojson) # underlay
m.keep_in_front(water_choro) # overlay 1
m.keep_in_front(sch) # overlay 2 (schools)
m.keep_in_front(hos) # overlay 3 (hospitals)
# Show map
m
Angola has one of the highest child mortality rates in the world, often linked and attributed to the spread of waterborne disease. Moreover, children, women and elderly are usually the main water fetchers within families, and can often commute for up to 2 hours one way to retrieve potable water. According to The Bergen Project, 37% of Luandan residents source water from city connected services, 25% source water from a private truck service, 22% source water from public stnadpipes and 16% source water from untreated rivers and illegal connections, highlighting the need for more reliable and connected pipe networks and access points.
# round hex columns to be to the hundredth decimal place
hex['children'] = hex['children'].round(2)
hex['women'] = hex['women'].round(2)
hex['elderly'] = hex['elderly'].round(2)
# Create a legend without HTML
e_legend = branca.colormap.LinearColormap(
colors=['#feebe2', '#ae017e'], # Adjust colors as needed
vmin=hex['elderly'].min(),
vmax=hex['elderly'].max(),
caption="Average % of Elderly Over 60",
)
c_legend = branca.colormap.LinearColormap(
colors=['#feebe2', '#ae017e'], # Adjust colors as needed
vmin=hex['children'].min(),
vmax=hex['children'].max(),
caption="Average % of Children Under 5",
)
w_legend = branca.colormap.LinearColormap(
colors=['#feebe2', '#ae017e'], # Adjust colors as needed
vmin=hex['women'].min(),
vmax=hex['women'].max(),
caption='Average % of Women of Reproductive Age (15-49)'
)
water_legend = branca.colormap.LinearColormap(
colors=['#A1CAF6', '#1E2F46'],
vmin=water['ID'].min(),
vmax=water['ID'].max(),
caption='% Access to Improved Water Sources'
)
import branca
# base map
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m) # separating function means basemap won't be included in layer control
# Water Choropleth
# water_choropleth = folium.Choropleth(
# data=water,
# geo_data=water,
# name='% Access to Improved Water Sources',
# columns=['idx', 'ID'],
# key_on='feature.properties.idx',
# fill_color='Blues',
# fill_opacity=1,
# line_opacity=0,
# legend_name='% Access to Improved Water Sources',
# highlight=True,
# bins=10,
# fixed_scale=True
# ).add_to(m)
# water_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(fields=['ID'],
# aliases=['% Access to Improved Water Sources'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap1 = linear.Blues_03.scale(water['ID'].min(), water['ID'].max())
colormap1.caption = "% Access to Improved Water Sources"
colormap1.add_to(m)
water_choro = folium.GeoJson(
water,
name='% Access to Improved Water Sources',
style_function=lambda feature: {
'fillColor': colormap1(feature['properties']['ID']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['ID'], aliases = ['% Access to Improved Water Sources'], labels=True, sticky=False),
).add_to(m)
# Elderly Choropleth
# elderly_choropleth = folium.Choropleth(
# data=hex,
# geo_data=hex,
# name='Average % of Elderly Over 60',
# columns=['hex_idx', 'elderly'],
# key_on='feature.properties.hex_idx',
# fill_color='Oranges',
# line_opacity=0,
# fill_opacity=0.5,
# bins=10,
# legend_name='Average % of Elderly Over 60',
# highlight=True,
# ).add_to(m)
# elderly_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(
# fields=['elderly', 'children'],
# aliases=['Average % of Elderly Over 60', 'Average % of Children Under 5'],
# localize=True,
# style=('background-color: black; color: white;')))
# Adjusting colormap length
colormap2 = linear.RdPu_03.scale(hex['elderly'].min(), hex['elderly'].max()) # Using 5 colors instead of 9
colormap2.caption = "Average % of Elderly Over 60"
colormap2.add_to(m)
elderly_choro = folium.GeoJson(
hex,
name='Average % of Elderly Over 60',
style_function=lambda feature: {
'fillColor' : 'transparent',
'color': colormap2(feature['properties']['elderly']),
'fillOpacity': 0,
'weight': 2, # Adjust the weight for a thinner outline
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=True,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5'], labels=True, sticky=False),
).add_to(m)
colormap3 = linear.RdPu_03.scale(hex['children'].min(), hex['children'].max())
colormap3.caption = "Average % of Children Under 5"
colormap3.add_to(m)
# child_choro = folium.GeoJson(
# hex,
# name='Average % of Children Under 5',
# style_function=lambda feature: {
# 'fillColor': colormap3(feature['properties']['children']),
# 'fillOpacity': 0.7,
# 'weight': 0,
# },
# highlight_function=lambda x: {'fillOpacity': 0.9},
# show=False,
# tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5'], labels=True, sticky=False),
# ).add_to(m)
child_choro = folium.GeoJson(
hex,
name='Average % of Children Under 5',
style_function=lambda feature: {
'fillColor': 'transparent', # Set fillColor to 'transparent'
'color': colormap3(feature['properties']['children']), # Use the colormap for the outline color
'fillOpacity': 0.0, # Set fillOpacity to 0 to make sure there's no fill
'weight': 4, # Adjust the weight to make the outline visible
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=False,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children'], aliases=['Average % of Elderly Over 60', 'Average % of Children Under 5'], labels=True, sticky=False),
).add_to(m)
# Child Choropleth
# child_choropleth = folium.Choropleth(
# data=hex,
# geo_data=hex,
# name='Average % of Children Under 5',
# columns=['hex_idx', 'children'],
# key_on='feature.properties.hex_idx',
# fill_color='PuRd',
# fill_opacity=0.5,
# line_opacity=0,
# bins=10,
# legend_name='Average % of Children Under 5',
# highlight=True,
# show=False
# ).add_to(m)
# child_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(
# fields=['children', 'elderly'],
# aliases=['Average % of Children Under 5', 'Average % of Elderly Over 60'],
# localize=True,
# style=('background-color: black; color: white;')))
# add layer control
folium.LayerControl(collapsed=False, overlay=False).add_to(m)
m.keep_in_front(water_choro) # underlay
m.keep_in_front(elderly_choro) # overlay 1
m.keep_in_front(child_choro) # overlay 2
m
In urbanized regions, access to sanitation sources is notably deficient, with a significant portion of schools and homes lacking basic facilities. This lack of access extends to the majority of urban areas, where the provision of sanitation infrastructure remains inadequate. To address these challenges, recent initiatives in Luanda have prioritized the development of interceptors aimed at enhancing sanitation infrastructure quality. Furthermore, efforts have been directed towards coastline beautification projects, reflecting a broader commitment to improving both the functionality and aesthetics of sanitation systems in the region. Despite these endeavors, ensuring widespread access to sanitation facilities remains a critical and ongoing challenge, particularly in densely populated urban centers.
Per the map, the most urbanized areas seem to have the least access to sanitation sources. Hospitals, schools, and homes tend to have particularly pronounced inaccessibility to basic sanitation; half of primary schools lack basic sanitation stations and nearly two-thirds of households do as well. Despite this, there has been a significant increase in sanitation infrastructure in Luanda in the lasy few years, and Luanda is ahead of other Angolan cities as it is one of only 7 cities with basic wastewater management.
# Base map
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m)
# wsf geojson
wsf_geojson = folium.GeoJson(
wsf_union,
name='Built-Up Area (2015)',
style_function=lambda x: {'fillColor': 'black', 'color': 'black', 'weight': 0, 'fillOpacity': 0.6},
highlight_function=lambda x: {'weight': 0, 'color': 'black'},
tooltip=folium.features.GeoJsonTooltip(fields=['idx'], aliases=['Built-Up'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
# # water Choropleth
# water_choropleth = folium.Choropleth(
# data=water,
# geo_data=water,
# name='% Access to Improved Water Sources',
# columns=['idx', 'ID'],
# key_on='feature.properties.idx',
# fill_color='Blues',
# fill_opacity=0.7,
# line_opacity=0,
# legend_name='% Access to Improved Water Sources',
# highlight=True,
# bins=10,
# fixed_scale=True
# ).add_to(m)
# water_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(fields=['ID'],
# aliases=['% Access to Improved Water Sources'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap = linear.YlGn_03.scale(sanitation['ID'].min(), sanitation['ID'].max())
colormap.caption = "% Access to Improved Sanitation Sources"
colormap.add_to(m)
san_choro = folium.GeoJson(
sanitation,
name='% Access to Improved Sanitation Sources',
style_function=lambda feature: {
'fillColor': colormap(feature['properties']['ID']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['ID'], aliases = ['% Access to Improved Sanitation Sources'], labels=True, sticky=False),
).add_to(m)
# Add schools and hospitals
sch = folium.GeoJson(
schools,
name='Schools',
style_function=lambda x: {'fillColor': '#ff00ff', 'color': '#ff00ff', 'weight': 0, 'fillOpacity': 1},
highlight_function=lambda x: {'weight': 0, 'color': '#ff00ff'},
tooltip=folium.features.GeoJsonTooltip(fields=['amenity'], aliases=['Schools'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
hos = folium.GeoJson(
hospital,
name='Hospitals',
style_function=lambda x: {'fillColor': 'yellow', 'color': 'yellow', 'weight': 0, 'fillOpacity': 1},
highlight_function=lambda x: {'weight': 0, 'color': 'yellow'},
tooltip=folium.features.GeoJsonTooltip(fields=['amenity'], aliases=['Hospitals'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
legend_html = '''
<div style="position: fixed;
bottom: 400px; right: 10px; width: 100px; height: 80px;
border:1px solid grey; z-index:9999; font-size:12px; background-color:white;
"> <b>Legend</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#black"></i> Built-Up Area<br>
<i class="fa fa-map-marker fa-1.5x" style="color:#ff00ff"></i> Schools<br>
<i class="fa fa-map-marker fa-1.5x" style="color:yellow"></i> Hospitals<br>
</div>
'''
# Add legend and CSS to map
m.get_root().html.add_child(folium.Element(legend_html))
# Add layer control
folium.LayerControl(collapsed=False, overlay=True).add_to(m)
# Organizing layers
m.keep_in_front(wsf_geojson) # underlay
m.keep_in_front(san_choro) # overlay 1
m.keep_in_front(sch) # overlay 2 (schools)
m.keep_in_front(hos) # overlay 3 (hospitals)
# Show map
m
The lack of access to sanitation services in the most urbanized parts of the city is often linked to a lack of investment in improved resources. Investment in basic sanitation on has been increasing for the past five years (approximately 102 billion Kz as of 2023), which shows the prioritization of improved sanitation services. Investment particularly benefits children due to the pronounced rates of diarrhea and malaria in children under 5.
# base map
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x],
zoom_start=10,
tiles=None,
control_scale=True,
# move zoom control to top right
zoom_control=False
)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m) # separating function means basemap won't be included in layer control
# Water Choropleth
# water_choropleth = folium.Choropleth(
# data=water,
# geo_data=water,
# name='% Access to Improved Water Sources',
# columns=['idx', 'ID'],
# key_on='feature.properties.idx',
# fill_color='Blues',
# fill_opacity=1,
# line_opacity=0,
# legend_name='% Access to Improved Water Sources',
# highlight=True,
# bins=10,
# fixed_scale=True
# ).add_to(m)
# water_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(fields=['ID'],
# aliases=['% Access to Improved Water Sources'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap1 = linear.YlGn_03.scale(sanitation['ID'].min(), sanitation['ID'].max())
colormap1.caption = "% Access to Improved Sanitation"
colormap1.add_to(m)
water_choro = folium.GeoJson(
sanitation,
name='% Access to Improved Sanitation Sources',
style_function=lambda feature: {
'fillColor': colormap1(feature['properties']['ID']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['ID'], aliases = ['% Access to Improved Sanitation'], labels=True, sticky=False),
).add_to(m)
# Elderly Choropleth
# elderly_choropleth = folium.Choropleth(
# data=hex,
# geo_data=hex,
# name='Average % of Elderly Over 60',
# columns=['hex_idx', 'elderly'],
# key_on='feature.properties.hex_idx',
# fill_color='Oranges',
# line_opacity=0,
# fill_opacity=0.5,
# bins=10,
# legend_name='Average % of Elderly Over 60',
# highlight=True,
# ).add_to(m)
# elderly_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(
# fields=['elderly', 'children'],
# aliases=['Average % of Elderly Over 60', 'Average % of Children Under 5'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap2 = linear.RdPu_03.scale(hex['elderly'].min(), hex['elderly'].max())
colormap2.caption = "Average % of Elderly Over 60"
colormap2.add_to(m)
elderly_choro = folium.GeoJson(
hex,
name='Average % of Elderly Over 60',
style_function=lambda feature: {
'fillColor': 'transparent',
'color': colormap2(feature['properties']['elderly']),
'fillOpacity': 0,
'weight': 4,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=True,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5'], labels=True, sticky=False),
).add_to(m)
colormap3 = linear.RdPu_03.scale(hex['children'].min(), hex['children'].max())
colormap3.caption = "Average % of Children Under 5"
colormap3.add_to(m)
child_choro = folium.GeoJson(
hex,
name='Average % of Children Under 5',
style_function=lambda feature: {
'fillColor': 'transparent',
'color': colormap3(feature['properties']['children']),
'fillOpacity': 0,
'weight': 4,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=False,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5'], labels=True, sticky=False),
).add_to(m)
# Child Choropleth
# child_choropleth = folium.Choropleth(
# data=hex,
# geo_data=hex,
# name='Average % of Children Under 5',
# columns=['hex_idx', 'children'],
# key_on='feature.properties.hex_idx',
# fill_color='PuRd',
# fill_opacity=0.5,
# line_opacity=0,
# bins=10,
# legend_name='Average % of Children Under 5',
# highlight=True,
# show=False
# ).add_to(m)
# child_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(
# fields=['children', 'elderly'],
# aliases=['Average % of Children Under 5', 'Average % of Elderly Over 60'],
# localize=True,
# style=('background-color: black; color: white;')))
# add layer control
folium.LayerControl(collapsed=False, overlay=False).add_to(m)
m.keep_in_front(water_choro) # underlay
m.keep_in_front(elderly_choro) # overlay 1
m.keep_in_front(child_choro) # overlay 2
m
While the rate of open defecation has reduced by more than half in the last two decades, Luanda still has a high dependence on open defection, most notably seen in completely urbanized areas of the city. Given 80% of the population lives in dense musseques, residents are more exposed to diarrhea diseases. Those living in peri-urban settlements with higher rates of reliance on open defecation can be up to 20 times more likely to get a diarrhea disease. Much investment has been concentrated on creating "open defecation free" communes to help increase accessibility to better waste practices.
# Base map
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m)
# wsf geojson
wsf_geojson = folium.GeoJson(
wsf_union,
name='Built-Up Area (2015)',
style_function=lambda x: {'fillColor': 'black', 'color': 'black', 'weight': 0, 'fillOpacity': 0.6},
highlight_function=lambda x: {'weight': 0, 'color': 'black'},
tooltip=folium.features.GeoJsonTooltip(fields=['idx'], aliases=['Built-Up'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
# # water Choropleth
# water_choropleth = folium.Choropleth(
# data=water,
# geo_data=water,
# name='% Access to Improved Water Sources',
# columns=['idx', 'ID'],
# key_on='feature.properties.idx',
# fill_color='Blues',
# fill_opacity=0.7,
# line_opacity=0,
# legend_name='% Access to Improved Water Sources',
# highlight=True,
# bins=10,
# fixed_scale=True
# ).add_to(m)
# water_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(fields=['ID'],
# aliases=['% Access to Improved Water Sources'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap = linear.YlOrBr_03.scale(defecation['ID'].min(), defecation['ID'].max())
colormap.caption = "% Reliance on Open Defecation Sources"
colormap.add_to(m)
choro = folium.GeoJson(
defecation,
name='% Access to Improved Open Defecation Sources',
style_function=lambda feature: {
'fillColor': colormap(feature['properties']['ID']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['ID'], aliases = ['% Reliance on Open Defecation Sources'], labels=True, sticky=False),
).add_to(m)
# Add schools and hospitals
sch = folium.GeoJson(
schools,
name='Schools',
style_function=lambda x: {'fillColor': '#ff00ff', 'color': '#ff00ff', 'weight': 0, 'fillOpacity': 1},
highlight_function=lambda x: {'weight': 0, 'color': '#ff00ff'},
tooltip=folium.features.GeoJsonTooltip(fields=['amenity'], aliases=['Schools'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
hos = folium.GeoJson(
hospital,
name='Hospitals',
style_function=lambda x: {'fillColor': 'yellow', 'color': 'yellow', 'weight': 0, 'fillOpacity': 1},
highlight_function=lambda x: {'weight': 0, 'color': 'yellow'},
tooltip=folium.features.GeoJsonTooltip(fields=['amenity'], aliases=['Hospitals'], localize=True, style=('background-color: black; color: white;'))
).add_to(m)
legend_html = '''
<div style="position: fixed;
bottom: 400px; right: 10px; width: 100px; height: 80px;
border:1px solid grey; z-index:9999; font-size:12px; background-color:white;
"> <b>Legend</b> <br>
<i class="fa fa-square fa-1.5x" style="color:#black"></i> Built-Up Area<br>
<i class="fa fa-map-marker fa-1.5x" style="color:#ff00ff"></i> Schools<br>
<i class="fa fa-map-marker fa-1.5x" style="color:yellow"></i> Hospitals<br>
</div>
'''
# Add legend and CSS to map
m.get_root().html.add_child(folium.Element(legend_html))
# Add layer control
folium.LayerControl(collapsed=False, overlay=True).add_to(m)
# Organizing layers
m.keep_in_front(wsf_geojson) # underlay
m.keep_in_front(choro) # overlay 1
m.keep_in_front(sch) # overlay 2 (schools)
m.keep_in_front(hos) # overlay 3 (hospitals)
# Show map
m
The urban core has the greatest reliance on open defecation, as well as the highest percentage of women of childbearing age, children, and elderly. Given the dense population of vulnerable populations in informal settlements lacking basic hygeinic defecation access, this perpetuates Luanda's longstanding problem of vectorborne and waterborne illness.
# base map
m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m) # separating function means basemap won't be included in layer control
# Water Choropleth
# water_choropleth = folium.Choropleth(
# data=water,
# geo_data=water,
# name='% Access to Improved Water Sources',
# columns=['idx', 'ID'],
# key_on='feature.properties.idx',
# fill_color='Blues',
# fill_opacity=1,
# line_opacity=0,
# legend_name='% Access to Improved Water Sources',
# highlight=True,
# bins=10,
# fixed_scale=True
# ).add_to(m)
# water_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(fields=['ID'],
# aliases=['% Access to Improved Water Sources'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap1 = linear.YlOrBr_03.scale(defecation['ID'].min(), defecation['ID'].max())
colormap1.caption = "% Reliance on Open Defecation Sources"
colormap1.add_to(m)
water_choro = folium.GeoJson(
defecation,
name='% Reliance on Open Defecation Sources',
style_function=lambda feature: {
'fillColor': colormap1(feature['properties']['ID']),
'fillOpacity': 0.7,
'weight': 0,
},
highlight_function=lambda x: {'fillOpacity': 0.9},
tooltip=folium.GeoJsonTooltip(fields=['ID'], aliases = ['% Reliance on Open Defecation Sources'], labels=True, sticky=False),
).add_to(m)
# Elderly Choropleth
# elderly_choropleth = folium.Choropleth(
# data=hex,
# geo_data=hex,
# name='Average % of Elderly Over 60',
# columns=['hex_idx', 'elderly'],
# key_on='feature.properties.hex_idx',
# fill_color='Oranges',
# line_opacity=0,
# fill_opacity=0.5,
# bins=10,
# legend_name='Average % of Elderly Over 60',
# highlight=True,
# ).add_to(m)
# elderly_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(
# fields=['elderly', 'children'],
# aliases=['Average % of Elderly Over 60', 'Average % of Children Under 5'],
# localize=True,
# style=('background-color: black; color: white;')))
# Add GeoJson layer with choropleth style
colormap2 = linear.RdPu_03.scale(hex['elderly'].min(), hex['elderly'].max())
colormap2.caption = "Average % of Elderly Over 60"
colormap2.add_to(m)
elderly_choro = folium.GeoJson(
hex,
name='Average % of Elderly Over 60',
style_function=lambda feature: {
'color': colormap2(feature['properties']['elderly']),
'fillOpacity': 0,
'weight': 4,
'fillColor': 'transparent'
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=True,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children', 'women'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5', 'Average % of Women of Reproductive Age'], labels=True, sticky=False),
).add_to(m)
colormap3 = linear.RdPu_03.scale(hex['children'].min(), hex['children'].max())
colormap3.caption = "Average % of Children Under 5"
colormap3.add_to(m)
child_choro = folium.GeoJson(
hex,
name='Average % of Children Under 5',
style_function=lambda feature: {
'color': colormap3(feature['properties']['children']),
'fillOpacity': 0,
'weight': 4,
'fillColor': 'transparent'
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=False,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children', 'women'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5', 'Average % of Women of Reproductive Age'], labels=True, sticky=False),
).add_to(m)
colormap4 = linear.RdPu_03.scale(hex['women'].min(), hex['women'].max())
colormap4.caption = "Average % of Women of Reproductive Age"
colormap4.add_to(m)
women_choro = folium.GeoJson(
hex,
name='Average % of Women of Reproductive Age',
style_function=lambda feature: {
'color': colormap4(feature['properties']['women']),
'fillOpacity': 0,
'weight': 4,
'fillColor': 'transparent'
},
highlight_function=lambda x: {'fillOpacity': 0.9},
show=False,
tooltip=folium.GeoJsonTooltip(fields=['elderly', 'children', 'women'], aliases = ['Average % of Elderly Over 60', 'Average % of Children Under 5', 'Average % of Women of Reproductive Age'], labels=True, sticky=False),
).add_to(m)
# Child Choropleth
# child_choropleth = folium.Choropleth(
# data=hex,
# geo_data=hex,
# name='Average % of Children Under 5',
# columns=['hex_idx', 'children'],
# key_on='feature.properties.hex_idx',
# fill_color='PuRd',
# fill_opacity=0.5,
# line_opacity=0,
# bins=10,
# legend_name='Average % of Children Under 5',
# highlight=True,
# show=False
# ).add_to(m)
# child_choropleth.geojson.add_child(folium.features.GeoJsonTooltip(
# fields=['children', 'elderly'],
# aliases=['Average % of Children Under 5', 'Average % of Elderly Over 60'],
# localize=True,
# style=('background-color: black; color: white;')))
# add layer control
folium.LayerControl(collapsed=False, overlay=False).add_to(m)
m.keep_in_front(water_choro) # underlay
m.keep_in_front(elderly_choro) # overlay 1
m.keep_in_front(child_choro) # overlay 2
m.keep_in_front(women_choro)
m
# glw = gpd.read_file(f'{city.lower()}_livestock.geojson').to_crs('epsg:4326')
# # Create a folium map centered on the AOI
# mymap = folium.Map(location=[-8.838333, 13.234444], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
# folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(mymap)
# aoi_bounds = aoi.total_bounds.tolist()
# mymap.fit_bounds([aoi_bounds[:2][::-1], aoi_bounds[2:][::-1]])
# # wsf geojson
# wsf_geojson = folium.GeoJson(
# wsf_union,
# name='Built-Up Area (2015)',
# style_function=lambda x: {'fillColor': 'black', 'color': 'black', 'weight': 0, 'fillOpacity': 0.6},
# highlight_function=lambda x: {'weight': 0, 'color': 'black'},
# tooltip=folium.features.GeoJsonTooltip(fields=['idx'], aliases=['Built-Up'], localize=True, style=('background-color: black; color: white;'))
# ).add_to(mymap)
# folium.GeoJson(
# aoi,
# style_function=lambda feature: {
# 'fillColor': 'transparent',
# 'color': 'gray',
# 'weight': 3
# },
# control = False).add_to(mymap)
# # Create a colormap based on the 'YlOrRd' scale and the 'raster_val' column
# colormap = linear.YlOrRd_03.scale(glw['raster_val'].min(), glw['raster_val'].max())
# colormap.caption = "Number of livestocks"
# colormap.add_to(mymap)
# # Add GeoJson layer with choropleth style
# folium.GeoJson(
# glw,
# name='Number of livestocks',
# style_function=lambda feature: {
# 'fillColor': colormap(feature['properties']['raster_val']),
# 'fillOpacity': 0.7,
# 'weight': 0,
# },
# highlight_function=lambda x: {'fillOpacity': 0.9},
# tooltip=folium.GeoJsonTooltip(fields=['raster_val'], aliases = ['Number of livestocks'], labels=True, sticky=False),
# ).add_to(mymap)
# # Add Layer Control to toggle the choropleth layer
# folium.LayerControl(collapsed=False, overlay=False).add_to(mymap)
# mymap
# # find geometry where wsf_union and imperviousness intersect
# wsf_union = wsf_union.to_crs('epsg:4326')
# imp = imp.to_crs('epsg:4326')
# # find geometry where wsf_union and imperviousness intersect
# wsf_union = wsf_union.to_crs('epsg:4326')
# imp = imp.to_crs('epsg:4326')
# union = gpd.overlay(wsf_union, imp, how='intersection')
# # find difference between union and imperviousness
# diff = gpd.overlay(wsf_union, union, how='difference')
# # find remaining geometry (impervious areas that are not part of the built-up area)
# remaining = gpd.overlay(imp, union, how='difference')
# diff['Group'] = 'Not Impervious, Urbanized'
# union['Group'] = 'Impervious, Urbanized'
# remaining['Group'] = 'Impervious, Not Urbanized'
# # combine the two dataframes
# total = pd.concat([diff, union, remaining], ignore_index=True)
# # map, diff, union and remaining as 3 diff colors
# m = folium.Map(location=[aoi.centroid.y, aoi.centroid.x], zoom_start=10, tiles=None, control_scale=True, zoom_control=False)
# folium.TileLayer('cartodbpositron', name='cartodbpositron', control=False).add_to(m)
# diff_geojson = folium.GeoJson(
# diff,
# name='Not Impervious, Urbanized',
# style_function=lambda x: {'fillColor': '#D95F30', 'color': '#D95F30', 'weight': 0, 'fillOpacity': 0.6},
# highlight_function=lambda x: {'weight': 0, 'color': '#D95F30'},
# tooltip=folium.features.GeoJsonTooltip(fields=['Group'], aliases=['Group'], localize=True, style=('background-color: black; color: white;'))
# ).add_to(m)
# union_geojson = folium.GeoJson(
# union,
# name='Impervious, Urbanized',
# style_function=lambda x: {'fillColor': '#6D8325', 'color': '#6D8325', 'weight': 0, 'fillOpacity': 0.6},
# highlight_function=lambda x: {'weight': 0, 'color': '#6D8325'},
# tooltip=folium.features.GeoJsonTooltip(fields=['Group'], aliases=['Group'], localize=True, style=('background-color: black; color: white;'))
# ).add_to(m)
# remaining_geojson = folium.GeoJson(
# remaining,
# name='Impervious, Not Urbanized',
# style_function=lambda x: {'fillColor': '#8785B2', 'color': '#8785B2', 'weight': 0, 'fillOpacity': 0.6},
# highlight_function=lambda x: {'weight': 0, 'color': '#8785B2'},
# tooltip=folium.features.GeoJsonTooltip(fields=['Group'], aliases=['Group'], localize=True, style=('background-color: black; color: white;'))
# ).add_to(m)
# folium.LayerControl(collapsed=False, overlay=True).add_to(m)
# # add legend
# legend_html = '''
# <div style="position: fixed;
# bottom: 400px; right: 10px; width: 200px; height: 100px;
# border:1px solid grey; z-index:9999; font-size:12px; background-color:white;
# "> <b>Legend</b> <br>
# <i class="fa fa-square fa-1.5x" style="color:#D95F30"></i> Not Impervious, Urbanized<br>
# <i class="fa fa-square fa-1.5x" style="color:#6D8325"></i> Impervious, Urbanized<br>
# <i class="fa fa-square fa-1.5x" style="color:#8785B2"></i> Impervious, Not Urbanized<br>
# </div>
# '''
# m.get_root().html.add_child(folium.Element(legend_html))
# m
# # find area of each row in area
# total['Area'] = total.area
# # variable called area which is the sum of the area column
# area = total['Area'].sum()
# # get % of each row in area
# total['Area_%'] = round((total['Area'] / area) * 100, 2)
# total = total[['Group', 'Area_%']]
# # total.plot.bar(x='Group', y='Area_%', color=['#D95F30', '#6D8325', '#8785B2'], legend=False)
# # plt.ylabel('Area (%)')
# # plt.xlabel('Group')
# # plt.title('Area of Imperviousness')
# # # print Area_% on top of each bar
# # for index, value in enumerate(total['Area_%']):
# # plt.text(index, value, str(value) + '%', ha='center', va='bottom')
# # plt.show()
# # Assuming 'total' is your DataFrame
# colors_dict = {'Not Impervious, Urbanized': '#D95F30', 'Impervious, Urbanized': '#6D8325', 'Impervious, Not Urbanized': '#8785B2'}
# colors = [{'Group': 'Not Impervious, Urbanized', 'color': '#D95F30'},
# {'Group': 'Impervious, Urbanized', 'color': '#6D8325'},
# {'Group': 'Impervious, Not Urbanized', 'color': '#8785B2'}]
# total.hvplot.bar(x='Group', y='Area_%', rot=45, color='color', legend=False, title='Area of Imperviousness', xlabel='Group', ylabel='Area (%)', width=600, height=400)
This SWOT analysis looks at key strengths, weaknesses, opportunities and threats to improving WASH conditions in Luanda.
Strengths | Weaknesses |
---|---|
Availability of natural water resources: Luanda benefits from proximity to water bodies such as the Atlantic Ocean, which can be tapped for desalination projects to increase freshwater supply, as well as extensive ground and surface water resources. | Inadequate infrastructure: Many areas in Luanda lack basic water and sanitation infrastructure, and the infrastructure that exists is aged and intended for a significantly smaller population. |
Increasing awareness and advocacy: Governmental advocacy, international funding, NGO awaerness, and community building have pushed greater awareness and need for improved infrastructure. | Rapid urbanization: The city's growth in population and expansion of urbanized land place extensive pressure on building, maintaining, and improving infrastructure. |
Potential for innovation: Current projects being funded have focused on expansive initiatives (coastline beautification, wastewater improvement, etc.). | Financial constraints: Dependence on external funding sources makes it challenging to develop sustainable projects. |
Strategic partnerships: Collaborations between government, international organizations, and private sector entities can leverage resources and expertise to address water and sanitation issues effectively. | Governance and institutional capacity: Weak top-down governance structures and institutional capacity can impede effective policy implementation and coordination. |
Opportunities | Threats |
Investment in infrastructure development: Opportunities exist for public and private sector investment in upgrading and expanding water and sanitation infrastructure to meet the growing demand. | Climate change impacts: The greatest threats include intense rainfall events, flooding of vital infrastructure, and shocks from unexpected weather events given the diverse climate. |
Behavior change interventions: Community advocacy and awareness allows for greater capacity building and resilience, especially alleviating the disproportionate impact on women, girls, and elderly. | Pollution and contamination: Pollution from industrial activities, urban runoff, and inadequate wastewater treatment poses risks to water quality, with Luanda suffering extensively from the burden of waterborne illnesses. |
Climate resilience measures: Addressing water-related hazards and climate change impacts through resilience-building measures presents opportunities for enhancing water security. | Gender and social disparities: Inequalities exacerbate disproportionate impact on certain community members. |
Capacity building and knowledge exchange: Engaging in capacity-building initiatives and knowledge-sharing platforms can strengthen local institutions and empower communities to actively participate in water and sanitation management. | Political instability: Political instability and conflicts can disrupt governance structures, hinder policy implementation, and undermine efforts to address water and sanitation challenges effectively. |