Skip to content

Commit 948515c

Browse files
authored
Add files via upload
1 parent 0784d18 commit 948515c

File tree

1 file changed

+162
-0
lines changed

1 file changed

+162
-0
lines changed

streamlit/flight_routes/app.py

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
import folium
2+
import streamlit as st
3+
from streamlit_folium import folium_static
4+
import pandas as pd
5+
from pyproj import Geod
6+
7+
8+
st.set_page_config(page_title='Flight Route Finder', layout='wide')
9+
st.title('Flight Route Finder')
10+
11+
st.markdown('This app uses historical flight data to visualize Non-Stop Flight Routes from '
12+
'any Country and Airport in the database.')
13+
14+
data_url = 'https://raw.githubusercontent.com/CoderCpy/Python_projects/refs/heads/main/data/flightroute/'
15+
csv_file = 'flight_routes.csv'
16+
17+
@st.cache_data
18+
def read_csv(url):
19+
df = pd.read_csv(url)
20+
return df
21+
22+
csv_url = data_url + csv_file
23+
df_routes = read_csv(csv_url)
24+
25+
26+
# This .csv file was created within flights_table_builder.ipynb, by using python code
27+
#to download, convert file type, merge and clean the data.
28+
29+
def value_change(category):
30+
st.session_state.df_routes = st.session_state.df_routes[st.session_state.df_routes[category]==st.session_state[category]]
31+
32+
if 'df_routes' not in st.session_state:
33+
st.session_state.df_routes=df_routes
34+
35+
cols = st.columns(2)
36+
country = cols[0].selectbox('Country', st.session_state.df_routes.origin_country.unique(), index=0,
37+
key='origin_country', placeholder="Choose a Country",
38+
on_change=value_change,
39+
kwargs={'category': 'origin_country'})
40+
airport = cols[1].selectbox('Airport', st.session_state.df_routes.Airport_name.unique(), index=0,
41+
key='Airport_name', placeholder="Choose an Airport",
42+
on_change=value_change, kwargs={'category': 'Airport_name'})
43+
44+
45+
def clear_state():
46+
st.session_state.df_routes=df_routes
47+
48+
st.button('Clear selection', on_click=clear_state)
49+
50+
# Defines a placeholder to display the distance and download button once computed.
51+
placeholder = st.empty()
52+
53+
54+
# Center location based on Airport coordinates.
55+
longitude_cutoff = 300
56+
s_origin_latitude = st.session_state.df_routes.iloc[0]['origin_lat']
57+
s_origin_longitude = st.session_state.df_routes.iloc[0]['origin_long']
58+
if s_origin_longitude > longitude_cutoff:
59+
s_origin_longitude -= 360
60+
coordinates = [s_origin_latitude, s_origin_longitude]
61+
62+
63+
m = folium.Map(location=coordinates, zoom_start=3, tiles = "CartoDB Positron")
64+
65+
66+
def generate_map(df_routes):
67+
longitude_cutoff = 300
68+
# add an input for map_name when it works.
69+
70+
g = Geod(ellps="WGS84")
71+
# From https://pyproj4.github.io/pyproj/stable/api/geod.html
72+
73+
74+
for i in range(len(st.session_state.df_routes)):
75+
76+
origin_latitude = st.session_state.df_routes.iloc[i]['origin_lat']
77+
origin_longitude = st.session_state.df_routes.iloc[i]['origin_long']
78+
if origin_longitude > longitude_cutoff:
79+
origin_longitude -= 360
80+
81+
82+
destination_latitude = st.session_state.df_routes.iloc[i]['dest_lat']
83+
destination_longitude = st.session_state.df_routes.iloc[i]['dest_long']
84+
if destination_longitude > longitude_cutoff:
85+
destination_longitude -= 360
86+
# This method of reducing far-east longitude points by 360 is from:
87+
# https://github.com/Leaflet/Leaflet/issues/82#issuecomment-1260488
88+
89+
route_color = '#3388ff'
90+
91+
gc_points = g.npts(origin_longitude, origin_latitude,
92+
destination_longitude, destination_latitude, 20)
93+
# Uses pyproj to create a list of great circle ('gc') points
94+
# that produce curvilinear airline routes. From:
95+
# https://pyproj4.github.io/pyproj/stable/api/geod.html?highlight=npts#pyproj.Geod.npts
96+
97+
revised_gc_points = []
98+
revised_gc_points.append((origin_latitude, origin_longitude))
99+
for item in gc_points:
100+
if item[0] > longitude_cutoff:
101+
new_lon = item[0] - 360
102+
else:
103+
new_lon = item[0]
104+
revised_gc_points.append((item[1], new_lon))
105+
# The coordinates in gc_points are stored in (longitude, latitude)
106+
# format, so this append statement flips them back into
107+
# (latitude, longitude) format for plotting.
108+
revised_gc_points.append((destination_latitude, destination_longitude))
109+
110+
folium.vector_layers.PolyLine(revised_gc_points, weight = 1, color = route_color).add_to(m)
111+
# Based on:
112+
# https://python-visualization.github.io/folium/modules.html#folium.vector_layers.PolyLine
113+
114+
# The following set of code creates a list of all airports contained
115+
# within the map, along with their coordinates.
116+
origin_airports = st.session_state.df_routes.copy()[['s_airport', 'origin_lat', 'origin_long']]
117+
origin_airports.columns=['code', 'lat', 'long']
118+
destination_airports = st.session_state.df_routes.copy()[['d_airport', 'dest_lat', 'dest_long']]
119+
destination_airports.columns=['code', 'lat', 'long']
120+
df_airports = pd.concat([origin_airports, destination_airports])
121+
df_airports.drop_duplicates('code', inplace=True)
122+
df_airports.reset_index(drop=True,inplace=True)
123+
124+
125+
# This for loop plots airport markers on the map.
126+
for i in range(len(df_airports)):
127+
if df_airports.iloc[i]['long'] > longitude_cutoff:
128+
airport_long = df_airports.iloc[i]['long'] - 360
129+
else:
130+
airport_long = df_airports.iloc[i]['long']
131+
if airport == True:
132+
folium.CircleMarker(location=[df_airports.iloc[i]['lat'],
133+
airport_long], radius = 2, fill = False,
134+
color = 'blue', fill_color = 'black', fill_opacity = 1).add_to(m)
135+
folium.Marker([df_airports.iloc[i]['lat'],
136+
airport_long],
137+
icon = folium.features.DivIcon(icon_anchor = (10, 20),
138+
html="<div><b>"+df_airports.iloc[i]['code']+"</b></div>")).add_to(m)
139+
# Tips on how to use Folium Markers.
140+
# https://python-visualization.github.io/folium/modules.html#folium.map.Marker
141+
# https://python-visualization.github.io/folium/modules.html#folium.features.DivIcon
142+
143+
else:
144+
folium.CircleMarker(location=[df_airports.iloc[i]['lat'],
145+
df_airports.iloc[i]['long']], tooltip = df_airports.iloc[i]['code'],
146+
radius = 1, fill = True, color = 'grey', fill_color = 'black',
147+
fill_opacity = 1).add_to(m)
148+
folium.Marker([df_airports.iloc[i]['lat'],
149+
airport_long],
150+
icon = folium.features.DivIcon(icon_anchor = (10, 20),
151+
html="<div><b>"+df_airports.iloc[i]['code']+"</b></div>")).add_to(m)
152+
153+
return m
154+
155+
route_map = generate_map(df_routes)
156+
157+
m.save('Routes.html')
158+
with open('Routes.html') as file:
159+
placeholder.download_button('Download Routes', data=file, file_name='Routes.html')
160+
161+
162+
folium_static(m, width=1200, height=800)

0 commit comments

Comments
 (0)