-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathhtmlbuilder.py
232 lines (199 loc) · 8.34 KB
/
htmlbuilder.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
#!/usr/bin/env python
''' Creates GEFS plots for a single location. Plots include high temperature, low temperature,
dewpoint, and precipitation. Program reads in CSV file created by ensemblemeans.py. Will
eventually create some HTML tables.
'''
import calendar
import datetime
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt
import matplotlib.dates as mdates
import numpy
import pandas
__author__ = 'Jason Godwin'
__license__ = 'GPL'
__maintainer__ = 'Jason Godwin'
__email__ = '[email protected]'
__status__ = 'Production'
# function for plotting ensemble members
def plotter(dataset,namestr,savestr,season,inittime):
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1,1,1)
plt.plot(dataset)
plt.grid()
# x axis
plt.xlim([dataset.index[0],dataset.index[-1]])
plt.xticks(dataset.index,rotation=90)
plt.xlabel('Date/Time (UTC)',fontsize=14)
ax.xaxis.set_major_locator(mdates.HourLocator(interval=24))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%a %b-%d'))
# y axis and title
plt.ylabel('Temperature (degrees Fahrenheit)',fontsize=14)
if season == 'warm':
plt.ylim([40,110])
plt.yticks(numpy.arange(40,110,5))
elif season == 'cold':
plt.ylim([0,90])
plt.yticks(numpy.arange(0,90,5))
elif season == 'dwpt':
plt.ylim([20,85])
plt.yticks(numpy.arange(20,85,5))
else:
plt.ylim([0,110])
plt.yticks(numpy.arange(0,110,5))
plt.title('GEFS Ensemble Daily %s (init: %s)' % (namestr,inittime),fontsize=16)
plt.savefig(savestr,bbox_inches='tight')
plt.close(fig)
# function for plotting precipitation in ensemble members
def precip_plotter(dataset,namestr,savestr,inittime):
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1,1,1)
plt.plot(numpy.cumsum(dataset))
plt.grid()
# x axis
plt.xlim([dataset.index[0],dataset.index[-1]])
plt.xticks(dataset.index,rotation=90)
plt.xlabel('Date/Time (UTC)',fontsize=14)
ax.xaxis.set_major_locator(mdates.HourLocator(interval=24))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%a %b-%d'))
# y axis and title
plt.ylim([0.0,4.0])
plt.yticks([0,0.1,0.25,0.50,1,2,3,4])
plt.ylabel('Precipitation (inches)',fontsize=14)
plt.title('GEFS Ensemble Daily %s (init: %s)' % (namestr,inittime),fontsize=16)
plt.savefig(savestr,bbox_inches='tight')
plt.close(fig)
# box and whisker plot function
def box_and_whisker(dataset,valid_dates,datatype,unitstr,namestr,savestr,inittime):
# reformat the date labels
valid_dates = [datetime.datetime.strftime(x,'%a %b-%d') for x in sorted(valid_dates)]
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1,1,1)
plt.boxplot(numpy.transpose(numpy.array(dataset)),whis='range',labels=valid_dates)
plt.grid()
# x axis
plt.xticks(rotation=90)
plt.xlabel('Date')
# set the y limits for temperatures
if 'Temperature' in namestr:
plt.ylim([0,110])
plt.yticks(numpy.arange(0,110,5))
elif 'Dewpoint' in namestr:
plt.ylim([20,85])
plt.yticks(numpy.arange(20,85,5))
elif 'Precip' in namestr:
plt.ylim([0.0,4.0])
plt.yticks([0,0.10,0.25,0.50,1.0,2.0,3.0,4.0])
# y axis and title
plt.ylabel('%s (%s)' % (datatype,unitstr),fontsize=14)
plt.title('GEFS Ensemble Daily %s (init: %s)' % (namestr,inittime),fontsize=16)
plt.savefig(savestr,bbox_inches='tight')
plt.close(fig)
### USER EDIT SECTION ###
savedir = '/home/jgodwin/Documents/python/python/gefs-plots' # directory to save pngs
locname = 'Dallas/Fort Worth, TX' # name of location to appear on plots
season = 'warm' # season to set temperature info
### END USER EDIT SECTION ###
# open CSVs containing ensemble information
max_temp_df = pandas.read_csv('%s/maxtemps.csv' % savedir,index_col=0)
min_temp_df = pandas.read_csv('%s/mintemps.csv' % savedir,index_col=0)
dpt_df = pandas.read_csv('%s/dewpoint.csv' % savedir,index_col=0)
precip_df = pandas.read_csv('%s/precip.csv' % savedir,index_col=0)
# convert index strings into datetime objects
max_temp_df.index = pandas.to_datetime(max_temp_df.index)
min_temp_df.index = pandas.to_datetime(min_temp_df.index)
dpt_df.index = pandas.to_datetime(dpt_df.index)
precip_df.index = pandas.to_datetime(precip_df.index)
# get individual dates and group max/min/mean values by date
dates = [datetime.datetime.strftime(i,'%m/%d/%Y') for i in max_temp_df.index]
highs = max_temp_df.groupby(lambda row: row.date()).max()
lows = min_temp_df.groupby(lambda row: row.date()).min()
dpts = dpt_df.groupby(lambda row: row.date()).mean()
precip = precip_df.groupby(lambda row: row.date()).sum()
# create list of valid dates and model run init time
valid_dates = [datetime.datetime.strptime(x,'%m/%d/%Y') for x in sorted(set(dates))]
inittime = datetime.datetime.strftime(max_temp_df.index[0],'%m/%d %H') + '00 UTC'
# truncate highs/lows since we are computing on closed intervals
# basically, if we don't do this, the 00Z runs will show a spike in high temperatures at the end
# of the run, and the highs will show a drop at the end of a 12Z run
if max_temp_df.index[0].hour == 0:
lows = lows[0:-2]
valid_dates_lo = valid_dates[0:-2]
valid_dates_hi = valid_dates
elif max_temp_df.index[0].hour == 12:
highs = highs[0:-2]
valid_dates_hi = valid_dates[0:-2]
valid_dates_lo = valid_dates
# plot forecasts
plotter(highs,'High Temperature at %s' % locname,'%s/highs.png' % savedir,season,inittime)
plotter(lows,'Low Temperature at %s' % locname,'%s/lows.png' % savedir,season,inittime)
plotter(dpts,'Mean Daily Dewpoint at %s' % locname,'%s/dwpt.png' % savedir,'dwpt',inittime)
precip_plotter(precip,'Run-Total Precip. at %s' % locname,'%s/precip.png' % savedir,inittime)
### PERCENT OF MEMBERS CONTAINING PRECIPITATION ###
precip_members = numpy.zeros(17)
for i in range(numpy.shape(precip)[0]):
precip_members[i] = numpy.shape((numpy.where(numpy.array(precip)[i,:]>0)))[1] / 20.0
# actual plot routine
fig = plt.figure(figsize=(12,8))
ax = fig.add_subplot(1,1,1)
plt.bar(valid_dates,precip_members,width=0.5,align='center')
plt.grid()
# add ensmble mean values to top of bars
rects = ax.patches
labels = ['%.02f' % x for x in numpy.nanmean(numpy.array(precip),axis=1)]
for rect,label in zip(rects,labels):
height = rect.get_height()
ax.text(rect.get_x() + rect.get_width()/2, height + 0.01, label, ha='center', va='bottom',\
fontsize=12)
# x axis
plt.xticks(rotation=90)
plt.xlim(valid_dates[0],valid_dates[-1])
plt.xlabel('Date/Time (UTC)',fontsize=14)
ax.xaxis.set_major_locator(mdates.DayLocator(interval=1))
ax.xaxis.set_major_formatter(mdates.DateFormatter('%a %b-%d'))
# y axis and title
plt.ylabel('Percent of Members',fontsize=14)
plt.ylim([0,1])
plt.yticks(numpy.arange(0,1,0.1))
vals = ax.get_yticks()
ax.set_yticklabels(['{:.0f}%'.format(x*100) for x in vals])
plt.title('GEFS Members Indicating Precipitation at %s (init: %s)' % (locname,inittime),\
fontsize=16)
plt.savefig('precip_percent.png',bbox_inches='tight')
plt.close(fig)
# create box and whisker plots
box_and_whisker(highs,valid_dates_hi,'Temperature','degrees Fahrenheit','High Temperature at %s' % \
locname,'%s/box_highs.png' % savedir,inittime)
box_and_whisker(lows,valid_dates_lo,'Temperature','degrees Fahrenheit','Low Temperature at %s' % \
locname,'%s/box_lows.png' % savedir,inittime)
box_and_whisker(dpts,valid_dates,'Dewpoint','degrees Fahrenheit','Mean Dewpoint at %s' % locname,\
'%s/box_dwpt.png' % savedir,inittime)
box_and_whisker(precip,valid_dates,'Precipitation','inches','Total Precip. at %s' % locname,\
'%s/box_precip.png' % savedir,inittime)
##### vv THIS PART STILL UNDER CONSTRUCTION vv #######
# create the webpage
html_file = open('%s/dfw.html' % savedir,'w')
# page header
html_info = """
<html>
<head>
<title>GEFS Viewer</title>
</head>
<body>
<h1>GEFS Temperature Plot for DFW</h1>
<h2>Initialized: %s UTC</h2>
""" % datetime.datetime.strftime(max_temp_df.index[0],'%m/%d/%Y %H:%M')
# create table header
html_info += '''
<table border=1 cols=22 width=1200px>
<tr><th>Valid Time</th>
'''
# create columns for each ensemble member
for i in range(1,21):
html_info += '''
<th>GEP %d</th>
''' % i
html_info += '<th>Ensemble Mean</th></tr>'
html_file.write(html_info)
html_file.close()