mattritchey commited on
Commit
549da37
·
1 Parent(s): 955f3be

Upload 2 files

Browse files
Files changed (2) hide show
  1. app.py +213 -0
  2. requirements.txt +12 -0
app.py ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """
3
+ Created on Fri Oct 14 10:35:25 2022
4
+
5
+ @author: mritchey
6
+ """
7
+ # streamlit run "C:\Users\mritchey\.spyder-py3\Python Scripts\streamlit projects\rtma\windtrial2_streamlit_rtma.py"
8
+ import datetime
9
+ import glob
10
+ import os
11
+ import urllib.request
12
+ import branca.colormap as cm
13
+ import folium
14
+ import numpy as np
15
+ import pandas as pd
16
+ import plotly.express as px
17
+ import rasterio
18
+ import rioxarray
19
+ import streamlit as st
20
+ from geopy.extra.rate_limiter import RateLimiter
21
+ from geopy.geocoders import Nominatim
22
+ from joblib import Parallel, delayed
23
+ from matplotlib import colors as colors
24
+ from streamlit_folium import st_folium
25
+ from threading import Thread
26
+
27
+
28
+ def download_file_get_data(url, rows, columns):
29
+ file = urllib.request.urlretrieve(url, url[-23:])[0]
30
+ rds = rioxarray.open_rasterio(file)
31
+ wind_mph = rds.rio.reproject("EPSG:4326")[0, rows, columns].values*2.23694
32
+ time = url[-15:-11]
33
+ return [wind_mph, time]
34
+
35
+
36
+ def threading(df_input, func_input):
37
+ starttime = time.time()
38
+ tasks_thread = df_input
39
+ results_thread = []
40
+
41
+ def thread_func(value_input):
42
+ response = func_input(value_input)
43
+ results_thread.append(response)
44
+ return True
45
+
46
+ threads = []
47
+ for i in range(len(tasks_thread)):
48
+ process = Thread(target=thread_func, args=[tasks_thread[i]])
49
+ process.start()
50
+ threads.append(process)
51
+
52
+ for process in threads:
53
+ process.join()
54
+ print(f'Time: {str(round((time.time()-starttime)/60,5))} Minutes')
55
+ return results_thread
56
+
57
+
58
+ def mapvalue2color(value, cmap):
59
+ if np.isnan(value):
60
+ return (1, 0, 0, 0)
61
+ else:
62
+ return colors.to_rgba(cmap(value), 0.7)
63
+
64
+
65
+ def geocode(address):
66
+ try:
67
+ address2 = address.replace(' ', '+').replace(',', '%2C')
68
+ df = pd.read_json(
69
+ f'https://geocoding.geo.census.gov/geocoder/locations/onelineaddress?address={address2}&benchmark=2020&format=json')
70
+ results = df.iloc[:1, 0][0][0]['coordinates']
71
+ lat, lon = results['y'], results['x']
72
+ except:
73
+ geolocator = Nominatim(user_agent="GTA Lookup")
74
+ geocode = RateLimiter(geolocator.geocode, min_delay_seconds=1)
75
+ location = geolocator.geocode(address)
76
+ lat, lon = location.latitude, location.longitude
77
+ return lat, lon
78
+
79
+
80
+ @st.cache
81
+ def get_grib_data(url, d, t):
82
+ file = urllib.request.urlretrieve(url, f'{d}{t}{type_wind}.grib2')[0]
83
+ return file
84
+
85
+
86
+ @st.cache
87
+ def graph_entire_day(d, rows, columns):
88
+ year, month, day = d[:4], d[4:6], d[6:8]
89
+ times = [f'0{str(i)}'[-2:] for i in range(0, 24)]
90
+ urls = [
91
+ f'https://mtarchive.geol.iastate.edu/{year}/{month}/{day}/grib2/ncep/RTMA/{d}{t}00_{type_wind.upper()}.grib2' for t in times]
92
+
93
+ results = Parallel(n_jobs=4)(
94
+ delayed(download_file_get_data)(i, rows, columns) for i in urls)
95
+
96
+ df_all = pd.DataFrame(results, columns=['MPH', 'Time'])
97
+ df_all['MPH'] = df_all['MPH'].round(2)
98
+ df_all['Time'] = pd.to_datetime(d+df_all['Time'], format='%Y%m%d%H%M')
99
+ return df_all
100
+
101
+
102
+ @st.cache
103
+ def convert_df(df):
104
+ return df.to_csv(index=0).encode('utf-8')
105
+
106
+
107
+ try:
108
+ for i in glob.glob('*.grib2'):
109
+ os.remove(i)
110
+ except:
111
+ pass
112
+
113
+ st.set_page_config(layout="wide")
114
+ col1, col2 = st.columns((2))
115
+
116
+ address = st.sidebar.text_input(
117
+ "Address", "123 Main Street, Columbus, OH 43215")
118
+ d = st.sidebar.date_input(
119
+ "Date", pd.Timestamp(2022, 9, 28)).strftime('%Y%m%d')
120
+
121
+ time = st.sidebar.selectbox('Time:', ('12 AM', '6 AM', '12 PM', '6 PM',))
122
+ type_wind = st.sidebar.selectbox('Type:', ('Gust', 'Wind'))
123
+ entire_day = st.sidebar.radio(
124
+ 'Graph Entire Day (Takes a Bit):', ('No', 'Yes'))
125
+
126
+ if time[-2:] == 'PM' and int(time[:2].strip()) < 12:
127
+ t = datetime.time(int(time[:2].strip())+12, 00).strftime('%H')+'00'
128
+ elif time[-2:] == 'AM' and int(time[:2].strip()) == 12:
129
+ t = '0000'
130
+ else:
131
+ t = datetime.time(int(time[:2].strip()), 00).strftime('%H')+'00'
132
+
133
+ year, month, day = d[:4], d[4:6], d[6:8]
134
+
135
+ url = f'https://mtarchive.geol.iastate.edu/{year}/{month}/{day}/grib2/ncep/RTMA/{d}{t}_{type_wind.upper()}.grib2'
136
+ file = get_grib_data(url, d, t)
137
+
138
+ lat, lon = geocode(address)
139
+
140
+ rds = rioxarray.open_rasterio(file)
141
+ projected = rds.rio.reproject("EPSG:4326")
142
+ wind_mph = projected.sel(x=lon, y=lat, method="nearest").values*2.23694
143
+
144
+ affine = projected.rio.transform()
145
+
146
+ rows, columns = rasterio.transform.rowcol(affine, lon, lat)
147
+
148
+ size = 40
149
+
150
+ projected2 = projected[0, rows-size:rows+size, columns-size:columns+size]
151
+
152
+ img = projected2.values*2.23694
153
+ boundary = projected2.rio.bounds()
154
+ left, bottom, right, top = boundary
155
+
156
+ img[img < 0.0] = np.nan
157
+
158
+ clat = (bottom + top)/2
159
+ clon = (left + right)/2
160
+
161
+ vmin = np.floor(np.nanmin(img))
162
+ vmax = np.ceil(np.nanmax(img))
163
+
164
+ colormap = cm.LinearColormap(
165
+ colors=['blue', 'lightblue', 'red'], vmin=vmin, vmax=vmax)
166
+
167
+ m = folium.Map(location=[lat, lon], zoom_start=9, height=500)
168
+
169
+ folium.Marker(
170
+ location=[lat, lon],
171
+ popup=f"{wind_mph[0].round(2)} MPH").add_to(m)
172
+
173
+ folium.raster_layers.ImageOverlay(
174
+ image=img,
175
+ name='Wind Speed Map',
176
+ opacity=.8,
177
+ bounds=[[bottom, left], [top, right]],
178
+ colormap=lambda value: mapvalue2color(value, colormap)
179
+ ).add_to(m)
180
+
181
+
182
+ folium.LayerControl().add_to(m)
183
+ colormap.caption = 'Wind Speed: MPH'
184
+ m.add_child(colormap)
185
+
186
+ with col1:
187
+ st.title('RTMA Model')
188
+ st.write(
189
+ f"{type_wind.title()} Speed: {wind_mph[0].round(2)} MPH at {time} UTC")
190
+ st_folium(m, height=500)
191
+
192
+
193
+ if entire_day == 'Yes':
194
+ df_all = graph_entire_day(d, rows, columns)
195
+ fig = px.line(df_all, x="Time", y="MPH")
196
+ with col2:
197
+ st.title('Analysis')
198
+ st.plotly_chart(fig)
199
+
200
+ csv = convert_df(df_all)
201
+
202
+ st.download_button(
203
+ label="Download data as CSV",
204
+ data=csv,
205
+ file_name=f'{d}.csv',
206
+ mime='text/csv')
207
+ else:
208
+ pass
209
+
210
+ st.markdown(""" <style>
211
+ #MainMenu {visibility: hidden;}
212
+ footer {visibility: hidden;}
213
+ </style> """, unsafe_allow_html=True)
requirements.txt ADDED
@@ -0,0 +1,12 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ branca==0.4.2
2
+ folium==0.12.1.post1
3
+ geopy==2.2.0
4
+ joblib==1.1.0
5
+ matplotlib==3.6.2
6
+ numpy==1.19.5
7
+ pandas==1.3.5
8
+ plotly==5.3.1
9
+ rasterio==1.2.10
10
+ rioxarray==0.10.3
11
+ streamlit==1.13.0
12
+ streamlit_folium==0.6.15