194 lines
7.8 KiB
Python
194 lines
7.8 KiB
Python
import dash
|
|
import dash_core_components as dcc
|
|
import dash_html_components as html
|
|
import pandas as pd
|
|
import plotly.express as px
|
|
from pycountry_convert import country_alpha2_to_country_name, country_name_to_country_alpha2, country_name_to_country_alpha3
|
|
from pycountry_convert.convert_country_alpha2_to_continent_code import COUNTRY_ALPHA2_TO_CONTINENT_CODE
|
|
from dash.dependencies import Output, Input
|
|
from pycountry_convert.country_wikipedia import WIKIPEDIA_COUNTRY_NAME_TO_COUNTRY_ALPHA2
|
|
|
|
external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']
|
|
app = dash.Dash(__name__, external_stylesheets=external_stylesheets)
|
|
text = "For **{0}**, map shows the countries with which it should open its " \
|
|
"air corridor basis the **{1}** Strictness Level of Policy. The map also shows the COVID Infection Rate for the countries from which the " \
|
|
"flights will operate."
|
|
|
|
def try_convert(country_name):
|
|
try:
|
|
return country_name_to_country_alpha3(country_name)
|
|
except:
|
|
return None
|
|
|
|
flights_data = pd.read_csv("dataset/merged-airlines.csv")
|
|
flights_data['CC'] = flights_data['source_airport_country'].apply(lambda x: try_convert(x))
|
|
latlon = pd.read_csv("dataset/latlon.csv", encoding='latin-1')
|
|
|
|
continent_filter = {}
|
|
for country_code, continent in COUNTRY_ALPHA2_TO_CONTINENT_CODE.items():
|
|
countries = continent_filter.get(continent, [])
|
|
try:
|
|
countries.append(country_alpha2_to_country_name(country_code))
|
|
except:
|
|
continue
|
|
continent_filter[continent] = countries
|
|
|
|
country_options = []
|
|
for country, country_code in WIKIPEDIA_COUNTRY_NAME_TO_COUNTRY_ALPHA2.items():
|
|
country_options.append({'label': country, 'value': country_code})
|
|
|
|
app.layout = html.Div([
|
|
html.Div([
|
|
html.Div([
|
|
html.H2('COVID Recovery Dashboard'),
|
|
html.H5('Team 162 - DVA Nightwalkers')
|
|
], className = 'columns', style = {'textAlign': 'center'})
|
|
]),
|
|
html.Div([
|
|
html.Div([
|
|
html.H6("Select Country and Policy", className = "control_label"),
|
|
html.P("Filter by Continent", className = "control_label"),
|
|
dcc.RadioItems(
|
|
id='continent-selector',
|
|
options = [
|
|
{'label': 'All', 'value': 'all'},
|
|
{'label': 'Africa', 'value': 'AF'},
|
|
{'label': 'Asia', 'value': 'AS'},
|
|
{'label': 'Europe', 'value': 'EU'},
|
|
{'label': 'Oceania', 'value': 'OC'},
|
|
{'label': 'North America', 'value': 'NA'},
|
|
{'label': 'South America', 'value': 'SA'}
|
|
],
|
|
value = 'all',
|
|
className = "dcc_control"
|
|
),
|
|
html.P("Select the Country", className = "control_label"),
|
|
dcc.Dropdown(
|
|
id = "country-selector",
|
|
options = country_options,
|
|
value = "US",
|
|
className = "dcc_control"
|
|
),
|
|
html.P("Select Strictness Level of Policy", className = "control_label"),
|
|
dcc.RadioItems(
|
|
id = 'strictness',
|
|
options = [
|
|
{'label': 'Lowest Level of Strictness', 'value': 'low'},
|
|
{'label': 'Moderate Level of Strictness', 'value': 'med'},
|
|
{'label': 'Highest Level of Strictness', 'value': 'high'}
|
|
],
|
|
value = 'low',
|
|
className = "dcc_control"
|
|
),
|
|
html.Span("Policy Selected:", className = "control_label"),
|
|
html.Span("Moderate", id="policy_selected", className = "control_label"),
|
|
html.P(),
|
|
html.Div(id="policy-indicator", style = {'padding': '0px 10px 10px 10px'})
|
|
], className = "pretty_container four columns"),
|
|
html.Div([
|
|
html.P(dcc.Markdown(text.format("United States", "Lowest")), id="text"),
|
|
html.P(),
|
|
dcc.Graph(
|
|
id = 'world_map'
|
|
)
|
|
], className = "pretty_container eight columns", id='rightCol')
|
|
], className = "row",),
|
|
], id="mainContainer"
|
|
)
|
|
|
|
@app.callback(Output('country-selector', 'options'),
|
|
[Input('continent-selector', 'value')])
|
|
def continent_filer_options(continent):
|
|
if continent == 'all':
|
|
return country_options
|
|
else:
|
|
options = []
|
|
countries = continent_filter[continent]
|
|
for country in countries:
|
|
options.append({
|
|
'label': country,
|
|
'value': country_name_to_country_alpha2(country)
|
|
})
|
|
return options
|
|
|
|
|
|
@app.callback([Output('policy-indicator', 'children'), Output('policy_selected', 'children'), Output('policy_selected', 'style')],
|
|
[Input('strictness', 'value')])
|
|
def policy_indicator(strictness):
|
|
policy = {
|
|
"low": [
|
|
{'label': 'Public Transport', 'value': 'yes'},
|
|
{'label': 'Internal Movements', 'value': 'yes'},
|
|
{'label': 'Schools', 'value': 'yes'},
|
|
{'label': 'Public Events', 'value': 'yes'},
|
|
{'label': 'Workplaces', 'value': 'yes'},
|
|
{'label': 'Stay at Home', 'value': 'yes'}
|
|
],
|
|
"med": [
|
|
{'label': 'Public Transport', 'value': 'no'},
|
|
{'label': 'Internal Movements', 'value': 'yes'},
|
|
{'label': 'Schools', 'value': 'no'},
|
|
{'label': 'Public Events', 'value': 'no'},
|
|
{'label': 'Workplaces', 'value': 'yes'},
|
|
{'label': 'Stay at Home', 'value': 'yes'}
|
|
],
|
|
"high": [
|
|
{'label': 'Public Transport', 'value': 'no'},
|
|
{'label': 'Internal Movements', 'value': 'no'},
|
|
{'label': 'Schools', 'value': 'no'},
|
|
{'label': 'Public Events', 'value': 'no'},
|
|
{'label': 'Workplaces', 'value': 'no'},
|
|
{'label': 'Stay at Home', 'value': 'no'}
|
|
]
|
|
}
|
|
restrictions = policy[strictness]
|
|
elements = []
|
|
for restriction in restrictions:
|
|
elements.append(html.P())
|
|
value = restriction['value']
|
|
label = restriction['label']
|
|
resp = "✔️" if value == "yes" else "❌"
|
|
elements.append(html.Span(resp, className = f"{value}"))
|
|
elements.append(html.Span(f" {label}"))
|
|
|
|
strictness_lbl = {
|
|
'high': 'Strict',
|
|
'med': 'Moderate',
|
|
'low': 'Lenient'
|
|
}
|
|
color = {
|
|
'low': 'green',
|
|
'med': 'orange',
|
|
'high': 'red'
|
|
}
|
|
|
|
return elements, strictness_lbl[strictness], {'color': color[strictness]}
|
|
|
|
@app.callback(
|
|
[Output('world_map', 'figure'), Output('text', 'children')],
|
|
[Input('country-selector', 'value'), Input('strictness', 'value')])
|
|
def update_graph(country_code, strictness):
|
|
country = country_alpha2_to_country_name(country_code)
|
|
dest_lat = latlon.loc[latlon['name'] == country]['latitude'].iloc[0]
|
|
dest_lon = latlon.loc[latlon['name'] == country]['longitude'].iloc[0]
|
|
dest_flights = flights_data[flights_data['dest_airport_country'] == country]
|
|
fig = px.choropleth(dest_flights, locationmode = "ISO-3", locations = 'CC', color = 'flight_capacity', color_continuous_scale="blues", template = 'seaborn')
|
|
|
|
for val in dest_flights.itertuples():
|
|
source = val[1]
|
|
try:
|
|
lat = latlon.loc[latlon['name'] == source]['latitude'].iloc[0]
|
|
lon = latlon.loc[latlon['name'] == source]['longitude'].iloc[0]
|
|
fig = fig.add_scattergeo(lat = [lat, dest_lat], lon = [lon, dest_lon], line = dict(width = 1, color = '#1F1F1F'),
|
|
mode = 'lines', showlegend = False)
|
|
except:
|
|
continue
|
|
strictness_level = {
|
|
'low': "Lowest",
|
|
'med': "Moderate",
|
|
'high': "Highest"
|
|
}[strictness]
|
|
return fig, dcc.Markdown(text.format(country, strictness_level))
|
|
|
|
if __name__ == '__main__':
|
|
app.run_server(debug=True, port=7777) |