Skip to content

Commit 0473961

Browse files
committed
✨ Add choropleth map overlay to all 6 charts - geographic context with consistent baseline z-values
1 parent 7ae6304 commit 0473961

File tree

7 files changed

+156
-15521
lines changed

7 files changed

+156
-15521
lines changed

docs/chart1-supplier-influence.html

Lines changed: 1 addition & 3879 deletions
Large diffs are not rendered by default.

docs/chart3-defense-systems.html

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

docs/chart4-multi-country-radar.html

Lines changed: 1 addition & 3879 deletions
Large diffs are not rendered by default.

docs/chart5-priorities-heatmap.html

Lines changed: 1 addition & 3879 deletions
Large diffs are not rendered by default.

docs/chart7-supplier-connections.html

Lines changed: 1 addition & 3879 deletions
Large diffs are not rendered by default.

geopolitical-dashboard/generate_charts_with_filters.py

Lines changed: 40 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,43 @@
1717
from geopolitical_app import create_threat_density_map
1818
from pages.chart1 import create_3d_surface_figure
1919
from pages.chart3 import create_3d_scatter_figure, create_choropleth_figure
20+
from pages.choropleth_map import create_choropleth_map
2021
from pages.chart4 import create_radar_figure
2122
from pages.chart5 import create_heatmap_figure
2223
from pages.chart7 import create_connection_map_figure
2324
from chart_data import get_data, filter_data
2425

26+
27+
def combine_choropleth_with_chart(fig_chart, chart_title):
28+
"""Combine a chart with a choropleth map overlay."""
29+
from plotly.subplots import make_subplots
30+
31+
fig_choropleth = create_choropleth_map("Geographic Overview")
32+
33+
combined_fig = make_subplots(
34+
rows=2, cols=1,
35+
subplot_titles=("Geographic Overview", chart_title),
36+
specs=[[{"type": "geo"}], [{"type": fig_chart.data[0].type if fig_chart.data else "scatter"}]],
37+
vertical_spacing=0.15
38+
)
39+
40+
# Add choropleth traces
41+
for trace in fig_choropleth.data:
42+
combined_fig.add_trace(trace, row=1, col=1)
43+
44+
# Add chart traces
45+
for trace in fig_chart.data:
46+
combined_fig.add_trace(trace, row=2, col=1)
47+
48+
# Update layout
49+
combined_fig.update_layout(
50+
height=1200,
51+
showlegend=True,
52+
title_text=chart_title
53+
)
54+
55+
return combined_fig
56+
2557
def wrap_with_filters_and_nav(html_content, chart_id, chart_title, filters_html=""):
2658
"""Wrap chart HTML with navigation and filters"""
2759

@@ -270,7 +302,8 @@ def main():
270302
# Chart 1: Supplier Influence with filters
271303
print("📊 Chart 1: Supplier Influence Surface")
272304
try:
273-
fig = create_3d_surface_figure("Influence", True)
305+
fig_chart = create_3d_surface_figure("Influence", True)
306+
fig = combine_choropleth_with_chart(fig_chart, "Supplier Influence Surface")
274307
html = fig.to_html(include_plotlyjs='cdn')
275308
filters_html = '''
276309
<div class="filter-group">
@@ -351,7 +384,8 @@ def main():
351384
# Chart 4: Multi-Country Radar with filters
352385
print("�� Chart 4: Multi-Country Radar")
353386
try:
354-
fig = create_radar_figure(None, "influence")
387+
fig_chart = create_radar_figure(None, "influence")
388+
fig = combine_choropleth_with_chart(fig_chart, "Multi-Country Radar Analysis")
355389
html = fig.to_html(include_plotlyjs='cdn')
356390
filters_html = '''
357391
<div class="filter-group">
@@ -381,7 +415,8 @@ def main():
381415
# Chart 5: Priorities Heatmap with filters
382416
print("📊 Chart 5: Priorities Heatmap")
383417
try:
384-
fig = create_heatmap_figure("country", "influence")
418+
fig_chart = create_heatmap_figure("country", "influence")
419+
fig = combine_choropleth_with_chart(fig_chart, "Priorities Heatmap")
385420
html = fig.to_html(include_plotlyjs='cdn')
386421
filters_html = '''
387422
<div class="filter-group">
@@ -410,7 +445,8 @@ def main():
410445
# Chart 7: Supplier Connections with filters
411446
print("📊 Chart 7: Supplier Connections")
412447
try:
413-
fig = create_connection_map_figure("all")
448+
fig_chart = create_connection_map_figure("all")
449+
fig = combine_choropleth_with_chart(fig_chart, "Supplier Connections")
414450
html = fig.to_html(include_plotlyjs='cdn')
415451
filters_html = '''
416452
<div class="filter-group">
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
"""
2+
Reusable Choropleth Map Component
3+
Displays a geographic overview map with Central Asian countries and neighboring regions
4+
"""
5+
6+
import plotly.graph_objects as go
7+
8+
# Country ISO codes mapping
9+
COUNTRIES_ISO = {
10+
"Kazakhstan": "KAZ",
11+
"Uzbekistan": "UZB",
12+
"Turkmenistan": "TKM",
13+
"Azerbaijan": "AZE",
14+
"Georgia": "GEO"
15+
}
16+
17+
# Neighboring countries for geographic context
18+
NEIGHBORING_COUNTRIES = {
19+
'RUS': 'Russia',
20+
'CHN': 'China',
21+
'AFG': 'Afghanistan',
22+
'IRN': 'Iran',
23+
'TUR': 'Turkey',
24+
'ARM': 'Armenia',
25+
'KGZ': 'Kyrgyzstan',
26+
'TJK': 'Tajikistan',
27+
'PAK': 'Pakistan',
28+
'IND': 'India',
29+
'MNG': 'Mongolia',
30+
'ROU': 'Romania',
31+
'BGR': 'Bulgaria',
32+
'GRC': 'Greece',
33+
'UKR': 'Ukraine',
34+
'POL': 'Poland',
35+
'SYR': 'Syria',
36+
'IRQ': 'Iraq',
37+
'SAU': 'Saudi Arabia',
38+
'ARE': 'UAE',
39+
'OMN': 'Oman',
40+
'QAT': 'Qatar',
41+
'BHR': 'Bahrain',
42+
'KWT': 'Kuwait',
43+
'JOR': 'Jordan',
44+
'ISR': 'Israel',
45+
'PSE': 'Palestine',
46+
'LBN': 'Lebanon',
47+
}
48+
49+
50+
def create_choropleth_map(title="Geographic Overview"):
51+
"""
52+
Create a choropleth map showing Central Asian countries and neighboring regions.
53+
54+
Args:
55+
title (str): Title for the choropleth map
56+
57+
Returns:
58+
go.Figure: Plotly figure object with choropleth map
59+
"""
60+
# Main countries (5)
61+
main_countries = ['Kazakhstan', 'Uzbekistan', 'Turkmenistan', 'Azerbaijan', 'Georgia']
62+
main_locations = [COUNTRIES_ISO[c] for c in main_countries]
63+
main_z = [100000000, 100000000, 100000000, 100000000, 100000000] # Consistent baseline
64+
65+
fig = go.Figure()
66+
67+
# Add main countries trace (with color)
68+
fig.add_trace(go.Choropleth(
69+
locations=main_locations,
70+
z=main_z,
71+
text=main_countries,
72+
colorscale='Blues',
73+
showscale=False,
74+
hovertemplate='<b>%{text}</b><extra></extra>',
75+
marker_line_color='white',
76+
marker_line_width=2,
77+
name='Main Countries'
78+
))
79+
80+
# Add neighboring countries trace (neutral gray)
81+
fig.add_trace(go.Choropleth(
82+
locations=list(NEIGHBORING_COUNTRIES.keys()),
83+
z=[50000000] * len(NEIGHBORING_COUNTRIES), # Neutral value
84+
text=list(NEIGHBORING_COUNTRIES.values()),
85+
colorscale=[[0, 'rgb(220, 220, 220)'], [1, 'rgb(200, 200, 200)']],
86+
showscale=False,
87+
hovertemplate='<b>%{text}</b> (Neighboring)<extra></extra>',
88+
marker_line_color='white',
89+
marker_line_width=1,
90+
name='Neighboring Countries'
91+
))
92+
93+
fig.update_layout(
94+
geo=dict(
95+
scope='asia',
96+
projection_type='natural earth',
97+
showland=True,
98+
landcolor='rgb(243, 243, 243)',
99+
coastlinecolor='rgb(204, 204, 204)',
100+
countrycolor='rgb(204, 204, 204)',
101+
showlakes=True,
102+
lakecolor='rgb(200, 220, 240)',
103+
center=dict(lon=70, lat=45),
104+
projection_scale=3
105+
),
106+
title=title,
107+
height=400,
108+
margin=dict(l=0, r=0, t=40, b=0)
109+
)
110+
111+
return fig

0 commit comments

Comments
 (0)