import dash
from dash import dcc, html, Input, Output, callback
import dash_bootstrap_components as dbc
import plotly.graph_objects as go
import pandas as pd
#read data
df_raw= pd.read_excel('nation.1751_2021.xlsx', sheet_name='Sheet1')
#read european nations => historical and current nations
european_nations = pd.read_excel('nation.1751_2021.xlsx', sheet_name='Sheet2')
#filter df_raw on european nations and data starting in 1950
dfd = df_raw[(df_raw['Nation'].isin(european_nations['Nation'].unique())) & \
(df_raw['Year'] > 1949)].reset_index()
#dfd = df_raw.copy()
dfd["Year"] = pd.to_datetime(dfd["Year"], format="%Y")
dfcols = dfd.columns.tolist()[3:]
russialist = ['KYRGYZSTAN','AZERBAIJAN','KAZAKHSTAN', 'TAJIKISTAN','TURKMENISTAN','BELARUS', 'MOLDOVA', 'LATVIA','LITHUANIA','ESTONIA','ARMENIA','GEORGIA','UZBEKISTAN','UKRAINE','RUSSIAN FEDERATION', 'USSR', ]
germanylist = ['FORMER GERMAN DEMOCRATIC REPUBLIC', 'FEDERAL REPUBLIC OF GERMANY','GERMANY']
czechlist = ['SLOVAKIA','CZECH REPUBLIC', 'CZECHOSLOVAKIA']
yugolist=['CROATIA','SLOVENIA', 'BOSNIA & HERZEGOVINA','MACEDONIA','KOSOVO','MONTENEGRO','SERBIA', 'YUGOSLAVIA (MONTENEGRO & SERBIA)','YUGOSLAVIA (FORMER SOCIALIST FEDERAL REPUBLIC)',]
colitems = html.Div(
[
dbc.Label("Choose a metric"),
dbc.RadioItems(
id="column_select",
options=[
{"label": col, "value": col}
for col in dfcols
],
value="Total CO2 emissions from fossil-fuels and cement production (thousand metric tons of C)",
className="mb-3"
),
]
)
viewmode = html.Div(
[
dbc.Label("Select viewmode"),
dbc.RadioItems(
id="view_select",
options=[
{"label": 'stacked (easier to compare totals)', "value": 'stacked'},
{'label': 'not stacked (easier to compare single nations)', 'value':'not-stacked'}
],
value="stacked",
className="mb-3"
),
]
)
thememode = html.Div([
html.Label("Theme Mode:", className="form-label"),
dbc.Switch(
id="theme-switch",
label="Dark Mode",
value=True,
className="mb-2"
)
] )
# Initialize the Dash app with Vizro theme
app = dash.Dash(
__name__,
external_stylesheets=[
dbc.themes.BOOTSTRAP,
"https://cdn.jsdelivr.net/gh/mckinsey/vizro@main/vizro-core/src/vizro/static/css/vizro.min.css"
]
)
# Define the layout
app.layout = dbc.Container([
# Header with theme switch
dbc.Row([
dbc.Col([
html.H1("CO2 emissions for some interesting european regions", style={'fontSize':'1.5rem'}, className=" mb-4"),
html.P('Mistakes are from the creator, not from the datasource.')
], width=8),
dbc.Col([
dbc.Card([
dbc.CardBody([
thememode, viewmode
])
])
], width=4)
], className="mb-4"),
# Main content
dbc.Row([
dbc.Col([
dbc.Card([
dbc.CardHeader(html.H4("Controls")),
dbc.CardBody([
html.Label("Select area of interest:", className="form-label"),
dcc.Dropdown(
id="nation_select",
options=[
{"label": 'USSR and successors', "value": 'russialist'},
{"label": 'Germany and predecessors', "value": 'germanylist'},
{"label": 'Czechoslovakia and successors', "value": 'czechlist'},
{"label": 'Yugoslavia and successors', "value":'yugolist'},
],
style={'color':'black'},
value='germanylist',
multi=False,
className="mb-3"
),
colitems,
])
])
], width=4),
dbc.Col([
dbc.Card([
dbc.CardHeader(html.H4(id='cardtitle')),
dbc.CardBody([
dcc.Graph(id='line_chart')
])
]),
html.H3('Datasource and more information'),
html.P('Hefner, M; Marland G; (2025): Global, Regional, and National Fossil-Fuel CO2 Emissions: 1751-2021 CDIAC-FF, Research Institute for Environment, Energy, and Economics, Appalachian State University. https://rieee.appstate.edu/projects-programs/cdiac')
], width=8),
],className="mb-4")
], fluid=True, id="main-container")
# Callback to switch themes
@callback(
Output("main-container", "className"),
Input("theme-switch", "value")
)
def switch_theme(dark_mode):
if dark_mode:
return "vizro-dark"
return "vizro-light"
@app.callback(
Output("line_chart", "figure"),
Output('cardtitle', 'children'),
Input("nation_select", "value"),
Input("column_select", "value"),
Input("view_select", "value"),
Input("theme-switch", "value")
)
def update_line_chart(nationlist, selected_column,selected_view,dark_mode):
fig = go.Figure()
russialist = ['KYRGYZSTAN','AZERBAIJAN','KAZAKHSTAN', 'TAJIKISTAN','TURKMENISTAN','BELARUS', 'MOLDOVA', 'LATVIA','LITHUANIA','ESTONIA','ARMENIA','GEORGIA','UZBEKISTAN','UKRAINE','RUSSIAN FEDERATION', 'USSR', ]
germanylist = ['FORMER GERMAN DEMOCRATIC REPUBLIC', 'FEDERAL REPUBLIC OF GERMANY','GERMANY']
czechlist = ['SLOVAKIA','CZECH REPUBLIC', 'CZECHOSLOVAKIA']
yugolist=['CROATIA','SLOVENIA', 'BOSNIA & HERZEGOVINA','MACEDONIA','KOSOVO','MONTENEGRO','SERBIA', 'YUGOSLAVIA (MONTENEGRO & SERBIA)','YUGOSLAVIA (FORMER SOCIALIST FEDERAL REPUBLIC)',]
#not very efficient, no switch or case or match
if nationlist == 'russialist':
nation=russialist
cardtitle='USSR and successors'
elif nationlist == 'germanylist':
nation = germanylist
cardtitle = 'Germany and predecessors'
elif nationlist == 'czechlist':
nation = czechlist
cardtitle='Czechoslovakia and successors'
else:
nation=yugolist
cardtitle='Yugoslavia and successors'
if selected_view == None:
selected_view = 'stacked'
if selected_column == None:
selected_column = "Total CO2 emissions from fossil-fuels and cement production (thousand metric tons of C)"
if nation == None:
nation=germanylist
if nation: # Check if at least one nation is selected
for nat in nation:
dff_nat = dfd[dfd['Nation'] == nat]
if selected_view == 'stacked':
fig.add_trace(go.Scatter(
x=dff_nat['Year'],
y=dff_nat[selected_column],
name=nat,
fill="tonexty" ,
mode="lines",
stackgroup='one'
))
else:
fig.add_trace(go.Scatter(
x=dff_nat['Year'],
y=dff_nat[selected_column],
name=nat,
mode="lines",
))
fig.update_layout(
paper_bgcolor='rgba(0,0,0,0)' if not dark_mode else '#1e1e1e',
plot_bgcolor='rgba(0,0,0,0)' if not dark_mode else '#2d2d2d',
font=dict(
family="Inter, system-ui, -apple-system, sans-serif",
color="#333333" if not dark_mode else "#ffffff",
weight="bold"
),
title = selected_column
)
return fig,cardtitle
# Wat is dit?
# Custom CSS for Vizro themes
app.index_string = '''
<!DOCTYPE html>
<html>
<head>
{%metas%}
<title>{%title%}</title>
{%favicon%}
{%css%}
<style>
body .vizro-dark {
background-color:rgb(26,26,26);
min-height:100vh;
}
.vizro-light {
background-color: #ffffff;
color: #333333;
}
.vizro-dark {
background-color: #1a1a1a;
color: #ffffff;
}
.vizro-dark .card {
background-color: #2d2d2d;
border-color: #404040;
color:white;
}
.vizro-dark .card-body {
color:white;
}
.vizro-dark .card-header {
background-color: #404040;
border-color: #404040;
color: #ffffff;
}
.vizro-light .card {
background-color: #ffffff;
border-color: #dee2e6;
}
.vizro-light .card-header {
background-color: #f8f9fa;
border-color: #dee2e6;
color: #333333;
}
</style>
</head>
<body>
{%app_entry%}
<footer>
{%config%}
{%scripts%}
{%renderer%}
</footer>
</body>
</html>
'''
if __name__ == "__main__":
app.run(debug=True)