import pandas as pd
import folium
from folium import plugins
import folium_legend
# Load stations
solarstations = pd.read_csv('../solarstations.csv', dtype={'Tier': str}).fillna('')
esmap_stations = pd.read_csv('../esmap_stations.csv', dtype={'Tier': str}).fillna('')
# Add esmap stations first so they are underneath
stations = pd.concat([solarstations, esmap_stations], axis='rows', ignore_index=True)
stations = stations[~stations['Instrumentation'].str.contains('G;Ds')] # remove Tier 3 stations
GHIImagery = "https://d2asdkx1wwwi7q.cloudfront.net/v20210621/ghi_global/{z}/z{z}_{x}x{y}.jpg"
DNIImagery = "https://d2asdkx1wwwi7q.cloudfront.net/v20210621/dni_global/{z}/z{z}_{x}x{y}.jpg"
GlobalSolarAtlasAttribution = "Source: GlobalSolarAtlas 2.0. Data from Solargis."
EsriImagery = "https://server.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer/tile/{z}/{y}/{x}"
EsriAttribution = "Tiles © Esri — Source: Esri, i-cubed, USDA, USGS, AEX, GeoEye, Getmapping, Aerogrid, IGN, IGP, UPR-EGP, and the GIS User Community"
# Create Folium map
m = folium.Map(
location=[0, 15],
zoom_start=1, min_zoom=1, max_bounds=True,
control_scale=True, # Adds distance scale in lower left corner
tiles='Cartodb Positron')
def station_status(time_period):
if time_period.endswith('-'):
return 'Active'
color = '#008000' # Green for active stations
elif (time_period == '') | time_period.endswith('?'):
return 'Unknown'
else:
return 'Inactive'
stations['Status'] = stations['Time period'].map(station_status)
status_dict = {
'Active': '#008000', # Green for active stations
'Unknown': '#3186cc', # Blue for stations with unknown status
'Inactive': '#ff422b', # Red for inactive stations
}
stations['Color'] = stations['Status'].map(status_dict)
z_order_dict = {'Active': 2, 'Unknown': 1, 'Inactive': 0}
stations['z_order'] = stations['Status'].map(z_order_dict)
stations['Tier'] = 2
stations.loc[stations['Instrumentation'].str.startswith('G;B;D'), 'Tier'] = 1
stations = stations.sort_values('z_order')
annual_irradiance = pd.read_csv('../data/nasa_power_annual_irradiance_global.csv', index_col=[0, 1])
for index, row in stations.iterrows():
lat_round = round(row['Latitude']*2-0.5, 0)/2 + 0.25
lon_round = round(row['Longitude']*2-0.5, 0)/2 + 0.25
try:
stations.loc[index, ['GHI', 'DHI', 'DNI']] = \
annual_irradiance.loc[(lat_round, lon_round), :].values
except KeyError as e:
continue
# Add each station to the map
for index, row in stations.iterrows():
folium.CircleMarker(
location=[row['Latitude'], row['Longitude']],
popup=folium.Popup(
f"{row['Station name']}, {row['Country']}<br>"
f"Tier: {row['Tier']}<br>"
f"Elevation: {row['Elevation']} m<br>"
f"GHI: {row['GHI']:.0f} kWh/m^2<br>"
f"DNI: {row['DNI']:.0f} kWh/m^2",
max_width="100"),
tooltip=row['Abbreviation'],
radius=5, color=row['Color'],
fill_color=row['Color'], fill=True).add_to(m)
folium.raster_layers.TileLayer(EsriImagery, name='World imagery', attr=EsriAttribution, show=False).add_to(m)
folium.raster_layers.TileLayer(GHIImagery, name='GHI', attr=GlobalSolarAtlasAttribution,
max_zoom=10, max_native_zoom=10, zoomOffset=1, show=False).add_to(m)
folium.raster_layers.TileLayer(DNIImagery, name='DNI', attr=GlobalSolarAtlasAttribution,
max_zoom=10, max_native_zoom=10, zoomOffset=1, show=False).add_to(m)
folium.LayerControl(position='topright').add_to(m)
# Additional options and plugins
# Note it's not possible to change the position of the scale
plugins.Fullscreen(position='bottomright').add_to(m) # Add full screen button to map
folium.LatLngPopup().add_to(m) # Show latitude/longitude when clicking on the map
# plugins.MiniMap(toggle_display=True, zoom_level_fixed=1, minimized=True, position='bottomright').add_to(m) # Add minimap to the map
# plugins.MeasureControl(position='topleft').add_to(m) # Add distance length measurement tool
# Create legend
legend = folium_legend.make_legend(status_dict.keys(), status_dict.values(), title="Station status")
m.get_root().html.add_child(legend) # Add Legend to map
# Show the map
m