def plotter(fdict): """ Go """ pgconn = get_dbconn("coop") ccursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] lagmonths = ctx["lag"] months = ctx["months"] month = ctx["month"] highyears = [int(x) for x in ctx["year"].split(",")] h = ctx["h"] wantmonth = month + lagmonths yearoffset = 0 if month + lagmonths < 1: wantmonth = 12 - (month + lagmonths) yearoffset = 1 wanted = [] deltas = [] for m in range(month, month + months): if m < 13: wanted.append(m) deltas.append(0) else: wanted.append(m - 12) deltas.append(-1) table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) elnino = {} ccursor.execute("""SELECT monthdate, soi_3m, anom_34 from elnino""") for row in ccursor: if row[0].month != wantmonth: continue elnino[row[0].year + yearoffset] = dict(soi_3m=row[1], anom_34=row[2]) ccursor.execute( "SELECT year, month, sum(precip), avg((high+low)/2.) " f"from {table} where station = %s GROUP by year, month", (station, ), ) if ccursor.rowcount == 0: raise NoDataFound("No Data Found.") yearly = {} for row in ccursor: (_year, _month, _precip, _temp) = row if _month not in wanted: continue effectiveyear = _year + deltas[wanted.index(_month)] nino = elnino.get(effectiveyear, {}).get("soi_3m", None) if nino is None: continue data = yearly.setdefault(effectiveyear, dict(precip=0, temp=[], nino=nino)) data["precip"] += _precip data["temp"].append(float(_temp)) fig = plt.figure(figsize=(10, 6)) ax = plt.axes([0.1, 0.12, 0.5, 0.75]) msg = ("[%s] %s\n%s\n%s SOI (3 month average)") % ( station, nt.sts[station]["name"], title(wanted), datetime.date(2000, wantmonth, 1).strftime("%B"), ) ax.set_title(msg) cmap = get_cmap(ctx["cmap"]) zdata = np.arange(-2.0, 2.1, 0.5) norm = mpcolors.BoundaryNorm(zdata, cmap.N) rows = [] xs = [] ys = [] for year in yearly: x = yearly[year]["precip"] y = np.average(yearly[year]["temp"]) xs.append(x) ys.append(y) val = yearly[year]["nino"] c = cmap(norm([val])[0]) if h == "hide" and val > -0.5 and val < 0.5: ax.scatter( x, y, facecolor="#EEEEEE", edgecolor="#EEEEEE", s=30, zorder=2, marker="s", ) else: ax.scatter(x, y, facecolor=c, edgecolor="k", s=60, zorder=3, marker="o") if year in highyears: ax.text(x, y + 0.2, "%s" % (year, ), ha="center", va="bottom", zorder=5) rows.append(dict(year=year, precip=x, tmpf=y, soi3m=val)) ax.axhline(np.average(ys), lw=2, color="k", linestyle="-.", zorder=2) ax.axvline(np.average(xs), lw=2, color="k", linestyle="-.", zorder=2) sm = plt.cm.ScalarMappable(norm, cmap) sm.set_array(zdata) cb = plt.colorbar(sm, extend="both") cb.set_label("<-- El Nino :: SOI :: La Nina -->") ax.grid(True) ax.set_xlim(left=-0.01) ax.set_xlabel("Total Precipitation [inch], Avg: %.2f" % (np.average(xs), )) ax.set_ylabel((r"Average Temperature $^\circ$F, " "Avg: %.1f") % (np.average(ys), )) df = pd.DataFrame(rows) ax2 = plt.axes([0.67, 0.6, 0.28, 0.35]) ax2.scatter(df["soi3m"].values, df["tmpf"].values) ax2.set_xlabel("<-- El Nino :: SOI :: La Nina -->") ax2.set_ylabel(r"Avg Temp $^\circ$F") slp, intercept, r_value, _, _ = stats.linregress(df["soi3m"].values, df["tmpf"].values) y1 = -2.0 * slp + intercept y2 = 2.0 * slp + intercept ax2.plot([-2, 2], [y1, y2]) ax2.text( 0.97, 0.9, "R$^2$=%.2f" % (r_value**2, ), ha="right", transform=ax2.transAxes, bbox=dict(color="white"), ) ax2.grid(True) ax3 = plt.axes([0.67, 0.1, 0.28, 0.35]) ax3.scatter(df["soi3m"].values, df["precip"].values) ax3.set_xlabel("<-- El Nino :: SOI :: La Nina -->") ax3.set_ylabel("Total Precip [inch]") slp, intercept, r_value, _, _ = stats.linregress(df["soi3m"].values, df["precip"].values) y1 = -2.0 * slp + intercept y2 = 2.0 * slp + intercept ax3.plot([-2, 2], [y1, y2]) ax3.text( 0.97, 0.9, "R$^2$=%.2f" % (r_value**2, ), ha="right", transform=ax3.transAxes, bbox=dict(color="white"), ) ax3.grid(True) return fig, df
def plotter(fdict): """ Go """ pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] delta = ctx['delta'] year = ctx['year'] nt = network.Table("%sCLIMATE" % (station[:2], )) table = "alldata_%s" % (station[:2], ) df = read_sql(""" WITH days as ( select generate_series('%s-01-01'::date, '%s-12-31'::date, '1 day'::interval)::date as day, to_char(generate_series('%s-01-01'::date, '%s-12-31'::date, '1 day'::interval)::date, 'mmdd') as sday ), climo as ( SELECT sday, avg(high) as avg_high, stddev(high) as stddev_high, avg(low) as avg_low, stddev(low) as stddev_low from """ + table + """ WHERE station = %s GROUP by sday ), thisyear as ( SELECT day, sday, high, low from """ + table + """ WHERE station = %s and year = %s ), thisyear2 as ( SELECT d.day, d.sday, t.high, t.low from days d LEFT JOIN thisyear t on (d.sday = t.sday) ) SELECT t.day, t.sday, t.high, t.low, c.avg_high, c.avg_low, c.stddev_high, c.stddev_low from thisyear2 t JOIN climo c on (t.sday = c.sday) ORDER by t.day ASC """, pgconn, params=(year, year, year, year, station, station, year), index_col='day') if df.empty: raise NoDataFound("No Data Found.") df.index.name = 'Date' df['high_sigma'] = (df['high'] - df['avg_high']) / df['stddev_high'] df['low_sigma'] = (df['low'] - df['avg_low']) / df['stddev_low'] (fig, ax) = plt.subplots(2, 1, sharex=True, figsize=(8, 6)) ax[0].plot(df.index.values, df['avg_high'].values, color='r', linestyle='-', label='Climate High') ax[0].plot(df.index.values, df['avg_low'].values, color='b', label='Climate Low') ax[0].set_ylabel(r"Temperature $^\circ\mathrm{F}$") ax[0].set_title("[%s] %s Climatology & %s Observations" % (station, nt.sts[station]['name'], year)) ax[0].plot(df.index.values, df['high'].values, color='brown', label='%s High' % (year, )) ax[0].plot(df.index.values, df['low'].values, color='green', label='%s Low' % (year, )) if delta == 'abs': ax[1].plot(df.index.values, (df.high - df.avg_high).values, color='r', label='High Diff %s - Climate' % (year)) ax[1].plot(df.index.values, (df.low - df.avg_low).values, color='b', label='Low Diff') ax[1].set_ylabel(r"Temp Difference $^\circ\mathrm{F}$") else: ax[1].plot(df.index.values, df.high_sigma.values, color='r', label='High Diff %s - Climate' % (year)) ax[1].plot(df.index.values, df.low_sigma.values, color='b', label='Low Diff') ax[1].set_ylabel(r"Temp Difference $\sigma$") ymax = max([df.high_sigma.abs().max(), df.low_sigma.abs().max()]) + 1 ax[1].set_ylim(0 - ymax, ymax) ax[1].legend(fontsize=10, ncol=2, loc='best') ax[1].grid(True) ax[0].legend(fontsize=10, ncol=2, loc=8) ax[0].grid() ax[0].xaxis.set_major_locator(mdates.MonthLocator(interval=1)) ax[0].xaxis.set_major_formatter(mdates.DateFormatter('%-d\n%b')) ax[0].set_xlim(df.index.min() - datetime.timedelta(days=3), df.index.max() + datetime.timedelta(days=3)) return fig, df
def get_context(fdict): """ Get the context""" pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] month = ctx['month'] ptype = ctx['type'] threshold = ctx['threshold'] table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) lag = "0 days" if month == 'fall': months = [9, 10, 11] label = "Fall (SON)" elif month == 'winter': months = [12, 1, 2] lag = "31 days" label = "Winter (DJF)" elif month == 'spring': months = [3, 4, 5] label = "Spring (MAM)" elif month == 'summer': months = [6, 7, 8] label = "Summer (JJA)" else: months = [int(month), ] label = calendar.month_name[int(month)] df = read_sql(""" WITH climo as ( SELECT to_char(valid, 'mmdd') as sday, high, low from ncdc_climate81 WHERE station = %s), day2day as ( SELECT extract(year from day + '""" + lag + """'::interval)::int as myyear, month, abs(high - lag(high) OVER (ORDER by day ASC)) as dhigh, abs(low - lag(low) OVER (ORDER by day ASC)) as dlow, abs((high+low)/2. - lag((high+low)/2.) OVER (ORDER by day ASC)) as dtemp from """ + table + """ WHERE station = %s), agg as ( SELECT myyear, avg(dhigh) as dhigh, avg(dlow) as dlow, avg(dtemp) as dtemp from day2day WHERE month in %s GROUP by myyear), agg2 as ( SELECT extract(year from day + '""" + lag + """'::interval)::int as myyear, max(o.high) as "max-high", min(o.high) as "min-high", avg(o.high) as "avg-high", stddev(o.high) as "std-high", max(o.low) as "max-low", min(o.low) as "min-low", avg(o.low) as "avg-low", stddev(o.low) as "std-low", avg((o.high + o.low)/2.) as "avg-temp", stddev((o.high + o.low)/2.) as "std-temp", max(o.precip) as "max-precip", sum(o.precip) as "sum-precip", avg(o.high) - avg(o.low) as "range-avghi-avglo", sum(case when o.high >= %s then 1 else 0 end) as "days-high-above", sum(case when o.high < %s then 1 else 0 end) as "days-high-below", sum(case when o.high >= c.high then 1 else 0 end) as "days-high-above-avg", sum(case when o.low >= %s then 1 else 0 end) as "days-lows-above", sum(case when o.low < c.low then 1 else 0 end) as "days-lows-below-avg", sum(case when o.low < %s then 1 else 0 end) as "days-lows-below" from """+table+""" o JOIN climo c on (o.sday = c.sday) where station = %s and month in %s GROUP by myyear) SELECT b.*, a.dhigh as "delta-high", a.dlow as "delta-low", a.dtemp as "delta_temp" from agg a JOIN agg2 b on (a.myyear = b.myyear) ORDER by b.myyear ASC """, pgconn, params=(nt.sts[station]['ncdc81'], station, tuple(months), threshold, threshold, threshold, threshold, station, tuple(months)), index_col='myyear') if df.empty: raise ValueError("No data was found for query") # Figure out the max min values to add to the row df2 = df[df[ptype] == df[ptype].max()] if df2.empty: raise ValueError("No data was found for query") xlabel = "Year, Max: %.2f %s%s" % (df[ptype].max(), df2.index.values[0], '+' if len(df2.index) > 1 else '') df2 = df[df[ptype] == df[ptype].min()] xlabel += ", Min: %.2f %s%s" % (df[ptype].min(), df2.index.values[0], '+' if len(df2.index) > 1 else '') ctx['xlabel'] = xlabel data = df[ptype].values ctx['data'] = data ctx['avgv'] = df[ptype].mean() ctx['df'] = df # Compute 30 year trailing average tavg = [None]*30 for i in range(30, len(data)): tavg.append(np.average(data[i-30:i])) ctx['tavg'] = tavg # End interval is inclusive ctx['a1981_2010'] = df.loc[1981:2010, ptype].mean() ctx['ptype'] = ptype ctx['station'] = station ctx['threshold'] = threshold ctx['month'] = month ctx['title'] = ("[%s] %s %s-%s" ) % (station, nt.sts[station]['name'], df.index.min(), df.index.max()) ctx['subtitle'] = ("%s %s" ) % (label, PDICT[ptype]) if ptype.find("days") == 0 and ptype.find('avg') == -1: ctx['subtitle'] += " (%s)" % (threshold,) units = r"$^\circ$F" if ctx['ptype'].find('precip') > 0: units = "inches" elif ctx['ptype'].find('days') > 0: units = "days" ctx['ylabel'] = "%s [%s]" % (PDICT[ctx['ptype']], units) return ctx
def plotter(fdict): """ Go """ pgconn = get_dbconn('coop') ccursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] threshold = ctx['threshold'] direction = ctx['direction'] varname = ctx['varname'] startyear = ctx['year'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) sql = """select year, max(case when """ + varname + """ < %s and month < 7 then extract(doy from day) else 0 end) as spring, max(case when """ + varname + """ < %s and month < 7 then day else null end) as spring_date, min(case when """ + varname + """ < %s and month > 6 then extract(doy from day) else 388 end) as fall, min(case when """ + varname + """ < %s and month > 6 then day else null end) as fall_date from """ + table + """ where station = %s GROUP by year ORDER by year ASC""" if direction == 'above': sql = """select year, min(case when """ + varname + """ > %s and month < 7 then extract(doy from day) else 183 end) as spring, min(case when """ + varname + """ > %s and month < 7 then day else null end) as spring_date, max(case when """ + varname + """ > %s and month > 6 then extract(doy from day) else 183 end) as fall, max(case when """ + varname + """ > %s and month > 6 then day else null end) as fall_date from """ + table + """ where station = %s GROUP by year ORDER by year ASC""" ccursor.execute(sql, (threshold, threshold, threshold, threshold, station)) rows = [] for row in ccursor: if row['year'] < startyear: continue if row['fall'] > 366: continue if row['fall'] == 183 and row['spring'] == 183: continue rows.append( dict(year=row['year'], spring=row['spring'], fall=row['fall'], spring_date=row['spring_date'], fall_date=row['fall_date'])) df = pd.DataFrame(rows) df['season'] = df['fall'] - df['spring'] res = """\ # IEM Climodat https://mesonet.agron.iastate.edu/climodat/ # Report Generated: %s # Climate Record: %s -> %s # Site Information: [%s] %s # Contact Information: Daryl Herzmann [email protected] 515.294.5978 # LENGTH OF SEASON FOR STATION NUMBER %s BASE TEMP=%s # LAST SPRING OCCURENCE FIRST FALL OCCURENCE YEAR MONTH DAY DOY MONTH DAY DOY LENGTH OF SEASON """ % (datetime.date.today().strftime("%d %b %Y"), nt.sts[station]['archive_begin'].date(), datetime.date.today(), station, nt.sts[station]['name'], station, threshold) for _, row in df.iterrows(): if row['spring_date'] is None or row['fall_date'] is None: continue res += ("%7i%4i%6i%4i %4i%6i%4i %.0f\n") % ( row['year'], row['spring_date'].month, row['spring_date'].day, row['spring'], row['fall_date'].month, row['fall_date'].day, row['fall'], row['season']) sts = datetime.date(2000, 1, 1) + datetime.timedelta(days=df['spring'].mean()) ets = datetime.date(2000, 1, 1) + datetime.timedelta(days=df['fall'].mean()) res += ("%7s%4i%6i%4i %4i%6i%4i %.0f\n") % ( "MEAN", sts.month, sts.day, df['spring'].mean(), ets.month, ets.day, df['spring'].mean(), df['season'].mean()) years = np.array(df['year']) spring = np.array(df['spring']) fall = np.array(df['fall']) s_slp, s_int, s_r, _, _ = stats.linregress(years, spring) f_slp, f_int, f_r, _, _ = stats.linregress(years, fall) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.bar(years, fall - spring, bottom=spring, ec='tan', fc='tan', zorder=1) for _v in [fall, spring]: avgv = int(np.average(_v)) ts = datetime.date(2000, 1, 1) + datetime.timedelta(days=(avgv - 1)) ax.text(years[-1] + 3, avgv, ts.strftime("Avg:\n%-d %b"), ha='left', va='center') ax.axhline(avgv, color='k') days = np.average(fall - spring) ax.text(1.02, 0.5, "<- %.1f days ->" % (days, ), transform=ax.transAxes, rotation=-90) ax.plot(years, years * s_slp + s_int, lw=3, zorder=2, label=r"%.2f $\frac{days}{100y}$ R$^2$=%.2f" % (s_slp * 100., s_r**2)) ax.plot(years, years * f_slp + f_int, lw=3, zorder=2, label=r"%.2f $\frac{days}{100y}$ R$^2$=%.2f" % (f_slp * 100., f_r**2)) ax.grid(True) title = PDICT.get(direction, '').replace('Temperature', PDICT2.get(varname)) ax.set_title(("[%s] %s\n" r"%s %s$^\circ$F") % (station, nt.sts[station]['name'], title, threshold)) ax.legend(ncol=2, fontsize=14, labelspacing=2) ax.set_yticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365)) ax.set_yticklabels(calendar.month_abbr[1:]) ax.set_ylim(min(spring) - 5, max(fall) + 30) ax.set_xlim(min(years) - 1, max(years) + 1) return fig, df, res
def plotter(fdict): """ Go """ pgconn = get_dbconn("coop") cursor = pgconn.cursor() ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] days = ctx["days"] days2 = ctx["days2"] date1 = ctx["date1"] date2 = ctx["date2"] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) interval = datetime.timedelta(days=days2) lbls = [] lbls2 = [] psigma = [] tsigma = [] aligns = [] align = ["top", "bottom"] now = date1 while now <= date2: sdays = [] for i in range(0, 0 - days, -1): sdays.append((now + datetime.timedelta(days=i)).strftime("%m%d")) cursor.execute(""" SELECT avg(p), stddev(p), avg(t), stddev(t), max(case when year = %s then p else -999 end), max(case when year = %s then t else -999 end) from (SELECT year, sum(precip) as p, avg((high+low)/2.) as t from %s WHERE station = '%s' and sday in %s GROUP by year) as foo """ % (now.year, now.year, table, station, str(tuple(sdays)))) row = cursor.fetchone() if row[0] is None: raise NoDataFound("No Data Found.") psigma.append((row[4] - row[0]) / row[1]) tsigma.append((row[5] - row[2]) / row[3]) lbls.append(now.strftime("%-m/%-d")) lbls2.append(now.strftime("%Y-%m-%d")) aligns.append(align[now.month % 2]) now += interval df = pd.DataFrame( dict( psigma=pd.Series(psigma), tsigma=pd.Series(tsigma), sdate=pd.Series(lbls2), )) tsigma = np.array(tsigma, "f") psigma = np.array(psigma, "f") ax.quiver( tsigma[:-1], psigma[:-1], tsigma[1:] - tsigma[:-1], psigma[1:] - psigma[:-1], scale_units="xy", angles="xy", scale=1, zorder=1, color="tan", ) for lbl, t, p, a in zip(lbls, tsigma, psigma, aligns): # Manual move label some for readiability if lbl == "7/15": t = float(t) + 0.1 p = float(p) + -0.2 ax.text(t, p, lbl, va=a, zorder=2) tmax = max([abs(np.min(tsigma)), abs(np.max(tsigma))]) + 0.5 ax.set_xlim(0 - tmax, tmax) pmax = max([abs(np.min(psigma)), abs(np.max(psigma))]) + 0.5 ax.set_ylim(0 - pmax, pmax) ax.set_ylabel(r"Precipitation Departure $\sigma$") ax.set_xlabel(r"Temperature Departure $\sigma$") ax.set_title(("%s - %s [%s] %s\n" "%s Day Trailing Departures plotted every %s days") % ( date1.strftime("%d %b %Y"), date2.strftime("%d %b %Y"), station, nt.sts[station]["name"], days, days2, )) ax.grid(True) ax.set_position([0.1, 0.1, 0.7, 0.8]) y = 0.96 pos = [1.01, 1.15, 1.22] ax.text(pos[0], y + 0.04, "Date", transform=ax.transAxes, fontsize=10) ax.text( pos[1], y + 0.04, r"T $\sigma$", transform=ax.transAxes, fontsize=10, ha="right", ) ax.text( pos[2], y + 0.04, r"P $\sigma$", transform=ax.transAxes, fontsize=10, ha="right", ) for lbl, t, p, a in zip(lbls, tsigma, psigma, aligns): ax.text(pos[0], y, "%s" % (lbl, ), transform=ax.transAxes, fontsize=10) ax.text( pos[1], y, "%.1f" % (t, ), transform=ax.transAxes, fontsize=10, color=get_color(t, "t"), ha="right", ) ax.text( pos[2], y, "%.1f" % (p, ), transform=ax.transAxes, fontsize=10, color=get_color(p, "p"), ha="right", ) y -= 0.04 return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = psycopg2.connect(database='coop', host='iemdb', user='******') station = fdict.get('station', 'IA0000') ptype = fdict.get('type', 'max-high') threshold = int(fdict.get('threshold', -99)) table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) df = read_sql(""" SELECT year, max(high) as "max-high", min(high) as "min-high", avg(high) as "avg-high", max(low) as "max-low", min(low) as "min-low", avg(low) as "avg-low", max(precip) as "max-precip", sum(precip) as "sum-precip", sum(case when high >= %s then 1 else 0 end) as "days-high-above", sum(case when low >= %s then 1 else 0 end) as "days-lows-above", sum(case when low < %s then 1 else 0 end) as "days-lows-below", avg(precip) as "avg-precip", avg(case when precip >= 0.01 then precip else null end) as "avg-precip2", sum(case when precip >= %s then 1 else 0 end) as "days-precip" from """+table+""" where station = %s GROUP by year ORDER by year ASC """, pgconn, params=(threshold, threshold, threshold, threshold, station), index_col='year') (fig, ax) = plt.subplots(1, 1) avgv = df[ptype].mean() data = df[ptype].values years = df.index.values # Compute 30 year trailing average tavg = [None]*30 for i in range(30, len(data)): tavg.append(np.average(data[i-30:i])) a1981_2010 = df.loc[1981:2011, ptype].mean() colorabove = 'tomato' colorbelow = 'dodgerblue' precision = "%.1f" if ptype in ['max-precip', 'sum-precip', 'avg-precip', 'avg-precip2', 'days-precip']: colorabove = 'dodgerblue' colorbelow = 'tomato' precision = "%.2f" bars = ax.bar(np.array(years) - 0.4, data, fc=colorabove, ec=colorabove) for i, bar in enumerate(bars): if data[i] < avgv: bar.set_facecolor(colorbelow) bar.set_edgecolor(colorbelow) lbl = "Avg: "+precision % (avgv,) ax.axhline(avgv, lw=2, color='k', zorder=2, label=lbl) lbl = "1981-2010: "+precision % (a1981_2010,) ax.axhline(a1981_2010, lw=2, color='brown', zorder=2, label=lbl) ax.plot(years, tavg, lw=1.5, color='g', zorder=4, label='Trailing 30yr') ax.plot(years, tavg, lw=3, color='yellow', zorder=3) ax.set_xlim(years[0] - 1, years[-1] + 1) if ptype.find('precip') == -1 and ptype.find('days') == -1: ax.set_ylim(min(data) - 5, max(data) + 5) ax.set_xlabel("Year") units = "$^\circ$F" if ptype.find('days') > 0: units = "days" elif ptype.find('precip') > 0: units = "inches" ax.set_ylabel("%s [%s]" % (PDICT[ptype], units)) ax.grid(True) ax.legend(ncol=3, loc='best', fontsize=10) msg = ("[%s] %s %s-%s %s" ) % (station, nt.sts[station]['name'], min(years), max(years), PDICT[ptype]) if ptype.find("days") == 0: msg += " (%s)" % (threshold,) tokens = msg.split() sz = len(tokens) / 2 ax.set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = psycopg2.connect(database='coop', host='iemdb', user='******') station = fdict.get('station', 'IA0000') varname = fdict.get('var', 'high') month = fdict.get('month', 'all') table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) yr = "year as yr" if month == 'all': months = range(1, 13) elif month == 'fall': months = [9, 10, 11] elif month == 'winter': months = [12, 1, 2] yr = "extract(year from o.day - '60 days'::interval) as yr" elif month == 'spring': months = [3, 4, 5] elif month == 'summer': months = [6, 7, 8] else: ts = datetime.datetime.strptime("2000-" + month + "-01", '%Y-%b-%d') # make sure it is length two for the trick below in SQL months = [ts.month, 999] df = read_sql(""" WITH avgs as ( SELECT sday, avg(high) as avg_high, avg(low) as avg_low, avg((high+low)/2.) as avg_temp from """ + table + """ WHERE station = %s GROUP by sday) SELECT """ + yr + """, sum(case when o.high > a.avg_high then 1 else 0 end) as high_above, sum(case when o.low > a.avg_low then 1 else 0 end) as low_above, sum(case when (o.high+o.low)/2. > a.avg_temp then 1 else 0 end) as avg_above, count(*) as days from """ + table + """ o, avgs a WHERE o.station = %s and o.sday = a.sday and month in %s GROUP by yr ORDER by yr ASC """, pgconn, params=(station, station, tuple(months)), index_col='yr') df['high_freq'] = df['high_above'] / df['days'].astype('f') * 100. df['low_freq'] = df['low_above'] / df['days'].astype('f') * 100. df['avg_freq'] = df['avg_above'] / df['days'].astype('f') * 100. (fig, ax) = plt.subplots(1, 1) avgv = df[varname + '_freq'].mean() colorabove = 'r' colorbelow = 'b' data = df[varname + '_freq'].values bars = ax.bar(df.index.values - 0.4, data, fc=colorabove, ec=colorabove) for i, bar in enumerate(bars): if data[i] < avgv: bar.set_facecolor(colorbelow) bar.set_edgecolor(colorbelow) ax.axhline(avgv, lw=2, color='k', zorder=2) txt = ax.text(bars[10].get_x(), avgv, "Avg: %.1f%%" % (avgv, ), color='yellow', fontsize=14, va='center') txt.set_path_effects([PathEffects.withStroke(linewidth=5, foreground="k")]) ax.set_ylim(0, 100) ax.set_yticks([0, 10, 25, 50, 75, 90, 100]) ax.set_xlabel("Year") ax.set_xlim(bars[0].get_x() - 1, bars[-1].get_x() + 1) ax.set_ylabel("Frequency [%]") ax.grid(True) msg = ("[%s] %s %s-%s Percentage of Days with %s Above Average (month=%s)" ) % (station, nt.sts[station]['name'], df.index.values.min(), df.index.values.max(), PDICT[varname], month.upper()) tokens = msg.split() sz = len(tokens) / 2 ax.set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] season = ctx['season'] direction = ctx['dir'] varname = ctx['var'] threshold = ctx['threshold'] startyear = ctx['year'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) b = "%s %s %s" % (varname, ">=" if direction == 'above' else '<', threshold) df = read_sql(""" SELECT extract(year from day + '%s month'::interval) as yr, sum(case when month in (12, 1, 2) and """ + b + """ then 1 else 0 end) as winter, sum(case when month in (3, 4, 5) and """ + b + """ then 1 else 0 end) as spring, sum(case when month in (6, 7, 8) and """ + b + """ then 1 else 0 end) as summer, sum(case when month in (9, 10, 11) and """ + b + """ then 1 else 0 end) as fall, sum(case when """ + b + """ then 1 else 0 end) as all from """ + table + """ WHERE station = %s and year >= %s GROUP by yr ORDER by yr ASC """, pgconn, params=(1 if season != 'all' else 0, station, startyear), index_col='yr') if df.empty: raise ValueError("No data found for query") (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) avgv = df[season].mean() colorabove = 'r' colorbelow = 'b' if direction == 'below': colorabove = 'b' colorbelow = 'r' bars = ax.bar(df.index.values, df[season], fc=colorabove, ec=colorabove, align='center') for i, bar in enumerate(bars): if df[season].values[i] < avgv: bar.set_facecolor(colorbelow) bar.set_edgecolor(colorbelow) ax.axhline(avgv, lw=2, color='k', zorder=2, label='Average') h_slope, intercept, r_value, _, _ = stats.linregress( df.index.values, df[season]) ax.plot(df.index.values, h_slope * df.index.values + intercept, '--', lw=2, color='k', label='Trend') ax.text(0.01, 0.99, "Avg: %.1f, slope: %.2f days/century, R$^2$=%.2f" % (avgv, h_slope * 100., r_value**2), transform=ax.transAxes, va='top', bbox=dict(color='white')) ax.set_xlabel("Year") ax.set_xlim(df.index.min() - 1, df.index.max() + 1) ax.set_ylim(0, max([df[season].max() + df[season].max() / 7., 3])) ax.set_ylabel("Number of Days") ax.grid(True) msg = ("[%s] %s %.0f-%.0f Number of Days [%s] " "with %s %s %g%s") % (station, nt.sts[station]['name'], df.index.min(), df.index.max(), PDICT2[season], PDICT3[varname], PDICT[direction], threshold, "$^\circ$F" if varname != 'precip' else 'inch') tokens = msg.split() sz = len(tokens) / 2 ax.set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) ax.legend(ncol=1) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt import matplotlib.colors as mpcolors COOP = psycopg2.connect(database='coop', host='iemdb', user='******') ccursor = COOP.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] lagmonths = ctx['lag'] months = ctx['months'] month = ctx['month'] highyears = [int(x) for x in ctx['year'].split(",")] h = ctx['h'] wantmonth = month + lagmonths yearoffset = 0 if month + lagmonths < 1: wantmonth = 12 - (month + lagmonths) yearoffset = 1 wanted = [] deltas = [] for m in range(month, month + months): if m < 13: wanted.append(m) deltas.append(0) else: wanted.append(m - 12) deltas.append(-1) table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) elnino = {} ccursor.execute("""SELECT monthdate, soi_3m, anom_34 from elnino""") for row in ccursor: if row[0].month != wantmonth: continue elnino[row[0].year + yearoffset] = dict(soi_3m=row[1], anom_34=row[2]) ccursor.execute( """ SELECT year, month, sum(precip), avg((high+low)/2.) from """ + table + """ where station = %s GROUP by year, month """, (station, )) yearly = {} for row in ccursor: (_year, _month, _precip, _temp) = row if _month not in wanted: continue effectiveyear = _year + deltas[wanted.index(_month)] nino = elnino.get(effectiveyear, {}).get('soi_3m', None) if nino is None: continue data = yearly.setdefault(effectiveyear, dict(precip=0, temp=[], nino=nino)) data['precip'] += _precip data['temp'].append(float(_temp)) fig = plt.figure(figsize=(10, 6)) ax = plt.axes([0.1, 0.12, 0.5, 0.75]) msg = ("[%s] %s\n%s\n%s SOI (3 month average)") % ( station, nt.sts[station]['name'], title(wanted), datetime.date(2000, wantmonth, 1).strftime("%B")) ax.set_title(msg) cmap = plt.get_cmap("RdYlGn") zdata = np.arange(-2.0, 2.1, 0.5) norm = mpcolors.BoundaryNorm(zdata, cmap.N) rows = [] xs = [] ys = [] for year in yearly: x = yearly[year]['precip'] y = np.average(yearly[year]['temp']) xs.append(x) ys.append(y) val = yearly[year]['nino'] c = cmap(norm([val])[0]) if h == 'hide' and val > -0.5 and val < 0.5: ax.scatter(x, y, facecolor='#EEEEEE', edgecolor='#EEEEEE', s=30, zorder=2, marker='s') else: ax.scatter(x, y, facecolor=c, edgecolor='k', s=60, zorder=3, marker='o') if year in highyears: ax.text(x, y + 0.2, "%s" % (year, ), ha='center', va='bottom', zorder=5) rows.append(dict(year=year, precip=x, tmpf=y, soi3m=val)) ax.axhline(np.average(ys), lw=2, color='k', linestyle='-.', zorder=2) ax.axvline(np.average(xs), lw=2, color='k', linestyle='-.', zorder=2) sm = plt.cm.ScalarMappable(norm, cmap) sm.set_array(zdata) cb = plt.colorbar(sm, extend='both') cb.set_label("<-- El Nino :: SOI :: La Nina -->") ax.grid(True) ax.set_xlim(left=-0.01) ax.set_xlabel("Total Precipitation [inch], Avg: %.2f" % (np.average(xs), )) ax.set_ylabel("Average Temperature $^\circ$F, Avg: %.1f" % (np.average(ys), )) df = pd.DataFrame(rows) ax2 = plt.axes([0.67, 0.6, 0.28, 0.35]) ax2.scatter(df['soi3m'].values, df['tmpf'].values) ax2.set_xlabel("<-- El Nino :: SOI :: La Nina -->") ax2.set_ylabel("Avg Temp $^\circ$F") slp, intercept, r_value, _, _ = stats.linregress(df['soi3m'].values, df['tmpf'].values) y1 = -2.0 * slp + intercept y2 = 2.0 * slp + intercept ax2.plot([-2, 2], [y1, y2]) ax2.text(0.97, 0.9, "R$^2$=%.2f" % (r_value**2, ), ha='right', transform=ax2.transAxes, bbox=dict(color='white')) ax2.grid(True) ax3 = plt.axes([0.67, 0.1, 0.28, 0.35]) ax3.scatter(df['soi3m'].values, df['precip'].values) ax3.set_xlabel("<-- El Nino :: SOI :: La Nina -->") ax3.set_ylabel("Total Precip [inch]") slp, intercept, r_value, _, _ = stats.linregress(df['soi3m'].values, df['precip'].values) y1 = -2.0 * slp + intercept y2 = 2.0 * slp + intercept ax3.plot([-2, 2], [y1, y2]) ax3.text(0.97, 0.9, "R$^2$=%.2f" % (r_value**2, ), ha='right', transform=ax3.transAxes, bbox=dict(color='white')) ax3.grid(True) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt from matplotlib.patches import Circle pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] month = ctx['month'] year = ctx['year'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) df = read_sql(""" SELECT year, sum(precip) as total_precip, sum(gdd50(high::numeric,low::numeric)) as gdd50 from """ + table + """ WHERE station = %s and month = %s GROUP by year """, pgconn, params=(station, month), index_col='year') if df.empty: raise ValueError("ERROR: No Data Found") gstats = df.gdd50.describe() pstats = df.total_precip.describe() df['precip_sigma'] = (df.total_precip - pstats['mean']) / pstats['std'] df['gdd50_sigma'] = (df.gdd50 - gstats['mean']) / gstats['std'] df['distance'] = (df.precip_sigma**2 + df.gdd50_sigma**2)**0.5 h_slope, intercept, r_value, _, _ = stats.linregress( df['gdd50_sigma'], df['precip_sigma']) y1 = -4.0 * h_slope + intercept y2 = 4.0 * h_slope + intercept (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.set_position([0.1, 0.12, 0.8, 0.78]) ax.scatter(df['gdd50_sigma'], df['precip_sigma'], label=None) ax.plot([-4, 4], [y1, y2], label="Slope=%.2f R$^2$=%.2f" % (h_slope, r_value**2)) xmax = df.gdd50_sigma.abs().max() + 0.25 ymax = df.precip_sigma.abs().max() + 0.25 ax.set_xlim(0 - xmax, xmax) ax.set_ylim(0 - ymax, ymax) events = df.query("distance > 2.5 or year == %.0f" % (year, )) for _year, row in events.iterrows(): ax.text(row['gdd50_sigma'], row['precip_sigma'], ' %.0f' % (_year, ), va='center') if year in df.index: c = Circle((0, 0), radius=df.loc[year].distance, facecolor='none') ax.add_patch(c) ax.set_xlabel(r"Growing Degree Day Departure ($\sigma$)") ax.set_ylabel(r"Precipitation Departure ($\sigma$)") ax.grid(True) ax.set_title( ("%s %s [%s]\n" "Growing Degree Day (base=50) + Precipitation Departure") % (calendar.month_name[month], nt.sts[station]['name'], station)) ax.legend(loc='upper right', bbox_to_anchor=(1.05, -0.04), ncol=2, fontsize=10) return fig, df
def plotter(fdict): """ Go """ pgconn = get_dbconn("coop", user="******") ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] thisyear = datetime.datetime.now().year year = ctx["year"] base = ctx["base"] ceiling = ctx["ceiling"] varname = ctx["var"] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) ab = nt.sts[station]["archive_begin"] if ab is None: raise NoDataFound("Unknown Station Metadata.") syear = max(ab.year, 1893) glabel = "%s%s%s" % (varname, base, ceiling) gfunc = "gddxx(%s, %s, high, low)" % (base, ceiling) title = "base=%s/ceil=%s" % (base, ceiling) if varname in ["hdd", "cdd"]: gfunc = "%s(high, low, %s)" % (varname, base) title = "base=%s" % (base, ) elif varname == "sdd": gfunc = "case when high > %s then high - %s else 0 end" % ( ceiling, ceiling, ) title = "base=%s" % (ceiling, ) df = read_sql( """ SELECT year, sday, """ + gfunc + """ as """ + glabel + """ from """ + table + """ WHERE station = %s and year > 1892 and sday != '0229' """, pgconn, params=(station, ), ) if df.empty: raise NoDataFound("No data Found.") # Do some magic! df2 = (df[[ "sday", glabel ]].groupby("sday").describe(percentiles=[0.05, 0.25, 0.75, 0.95])) df2 = df2.unstack(level=-1) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.plot( np.arange(1, 366), df2[(glabel, "mean")], color="r", zorder=2, lw=2.0, label="Average", ) _data = df[df["year"] == year][[glabel, "sday"]] _data.sort_values(by="sday", inplace=True) ax.scatter( np.arange(1, _data[glabel].shape[0] + 1), _data[glabel], color="b", zorder=2, label="%s" % (year, ), ) ax.bar( np.arange(1, 366), df2[(glabel, "95%")] - df2[(glabel, "5%")], bottom=df2[(glabel, "5%")], ec="tan", fc="tan", zorder=1, label="5-95 Percentile", ) ax.bar( np.arange(1, 366), df2[(glabel, "75%")] - df2[(glabel, "25%")], bottom=df2[(glabel, "25%")], ec="lightblue", fc="lightblue", zorder=1, label="25-75 Percentile", ) ax.set_xlim(0, 367) if varname == "gdd": ax.set_ylim(-0.25, 40) ax.grid(True) ax.set_title("%s-%s %s [%s]\n%s %s (%s)" % ( syear, thisyear, nt.sts[station]["name"], station, year, PDICT[varname], title, )) ax.set_ylabel(r"Daily Accumulation $^{\circ}\mathrm{F}$") ax.set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335)) ax.legend(ncol=2) ax.set_xticklabels(calendar.month_abbr[1:]) # collapse the multiindex for columns df = pd.DataFrame(df2) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = get_dbconn('coop') ccursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] binsize = ctx['binsize'] month = ctx['month'] table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) if month == 'all': months = range(1, 13) elif month == 'fall': months = [9, 10, 11] elif month == 'winter': months = [12, 1, 2] elif month == 'spring': months = [3, 4, 5] elif month == 'summer': months = [6, 7, 8] else: ts = datetime.datetime.strptime("2000-"+month+"-01", '%Y-%b-%d') # make sure it is length two for the trick below in SQL months = [ts.month, 999] ccursor.execute(""" SELECT high, low from """+table+""" WHERE station = %s and year > 1892 and high >= low and month in %s """, (station, tuple(months))) highs = [] lows = [] for row in ccursor: highs.append(row[0]) lows.append(row[1]) bins = np.arange(-20, 121, binsize) H, xedges, yedges = np.histogram2d(lows, highs, bins) rows = [] for i, x in enumerate(xedges[:-1]): for j, y in enumerate(yedges[:-1]): rows.append(dict(high=y, low=x, count=H[i, j])) df = pd.DataFrame(rows) years = float( datetime.datetime.now().year - nt.sts[station]['archive_begin'].year ) H = np.ma.array(H / years) H.mask = np.where(H < (1./years), True, False) ar = np.argwhere(H.max() == H) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) res = ax.pcolormesh(xedges, yedges, H.transpose()) fig.colorbar(res, label="Days per Year") ax.grid(True) ax.set_title(("%s [%s]\n" "Daily High vs Low Temp Histogram (month=%s)" ) % (nt.sts[station]['name'], station, month.upper())) ax.set_ylabel(r"High Temperature $^{\circ}\mathrm{F}$") ax.set_xlabel(r"Low Temperature $^{\circ}\mathrm{F}$") x = ar[0][0] y = ar[0][1] ax.text(0.65, 0.15, ("Largest Frequency: %.1f days\n" "High: %.0f-%.0f Low: %.0f-%.0f" ) % (H[x, y], yedges[y], yedges[y+1], xedges[x], xedges[x+1]), ha='center', va='center', transform=ax.transAxes, bbox=dict(color='white')) ax.axhline(32, linestyle='-', lw=1, color='k') ax.text(120, 32, r"32$^\circ$F", va='center', ha='right', color='white', bbox=dict(color='k'), fontsize=8) ax.axvline(32, linestyle='-', lw=1, color='k') ax.text(32, 120, r"32$^\circ$F", va='top', ha='center', color='white', bbox=dict(facecolor='k', edgecolor='none'), fontsize=8) return fig, df
def main(): """Go Main Go""" nt = network.Table("AWOS") qdict = loadqc() pgconn = get_dbconn("iem", user="******") icursor = pgconn.cursor() # We run at 12z now12z = datetime.datetime.utcnow() now12z = now12z.replace(hour=12, minute=0, second=0, microsecond=0, tzinfo=pytz.utc) today6z = now12z.replace(hour=6) today0z = now12z.replace(hour=0) yesterday6z = today6z - datetime.timedelta(days=1) yesterday12z = now12z - datetime.timedelta(days=1) fmt = "%-6s:%-19s: %3s / %3s / %5s / %4s / %2s\n" shef_fn = "/tmp/awos_rtp.shef" out = open(shef_fn, "w") out.write( ("\n" "\n" "\n" ".BR DMX %s Z DH06/TAIRVX/DH12/TAIRVP/PPDRVZ/SFDRVZ/SDIRVZ\n" ": IOWA AWOS RTP FIRST GUESS PROCESSED BY THE IEM\n" ": 06Z to 06Z HIGH TEMPERATURE FOR %s\n" ": 00Z TO 12Z TODAY LOW TEMPERATURE\n" ": 12Z YESTERDAY TO 12Z TODAY RAINFALL\n" ": ...BASED ON REPORTED OBS...\n") % (now12z.strftime("%m%d"), yesterday6z.strftime("%d %b %Y").upper())) # 6z to 6z high temperature highs = {} sql = """SELECT id, round(max(tmpf)::numeric,0) as max_tmpf, count(tmpf) as obs FROM current_log c, stations t WHERE t.iemid = c.iemid and t.network = 'AWOS' and valid >= %s and valid < %s and tmpf > -99 GROUP by id """ args = (yesterday6z, today6z) icursor.execute(sql, args) for row in icursor: if qdict.get(row[0], {}).get("tmpf"): continue highs[row[0]] = row[1] # 12z to 12z precip pcpn = {} sql = """ select id, sum(precip) from (select id, extract(hour from valid) as hour, max(phour) as precip from current_log c, stations t WHERE t.network = 'AWOS' and t.iemid = c.iemid and valid >= %s and valid < %s GROUP by id, hour) as foo GROUP by id """ args = (yesterday12z, now12z) icursor.execute(sql, args) for row in icursor: if qdict.get(row[0], {}).get("precip") or row[1] is None: continue pcpn[row[0]] = "%5.2f" % (row[1], ) # 0z to 12z low temperature lows = {} sql = """ SELECT id, round(min(tmpf)::numeric,0) as min_tmpf, count(tmpf) as obs FROM current_log c JOIN stations t on (t.iemid = c.iemid) WHERE t.network = 'AWOS' and valid >= %s and valid < %s and tmpf > -99 GROUP by id """ args = (today0z, now12z) icursor.execute(sql, args) for row in icursor: if qdict.get(row[0], {}).get("tmpf"): continue lows[row[0]] = row[1] ids = list(nt.sts.keys()) ids.sort() for myid in ids: out.write(fmt % ( myid, nt.sts[myid]["name"], highs.get(myid, "M"), lows.get(myid, "M"), pcpn.get(myid, "M"), "M", "M", )) out.write(".END\n") out.close() cmd = ("/home/ldm/bin/pqinsert -p 'plot ac %s0000 awos_rtp.shef " "awos_rtp.shef shef' %s") % (now12z.strftime("%Y%m%d"), shef_fn) subprocess.call(cmd, shell=True) os.unlink(shef_fn)
def plotter(fdict): """ Go """ pgconn = get_dbconn("coop") ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] binsize = ctx["binsize"] month = ctx["month"] year = ctx.get("year") table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) if month == "all": months = range(1, 13) elif month == "fall": months = [9, 10, 11] elif month == "winter": months = [12, 1, 2] elif month == "spring": months = [3, 4, 5] elif month == "summer": months = [6, 7, 8] else: ts = datetime.datetime.strptime("2000-" + month + "-01", "%Y-%b-%d") # make sure it is length two for the trick below in SQL months = [ts.month, 999] ddf = read_sql( f"SELECT high, low, year, month from {table} WHERE station = %s " "and year > 1892 and high >= low and month in %s", pgconn, params=(station, tuple(months)), index_col=None, ) if ddf.empty: raise NoDataFound("No Data Found.") bins = np.arange(-40, 121, binsize) hist, xedges, yedges = np.histogram2d(ddf["low"], ddf["high"], bins) rows = [] for i, xedge in enumerate(xedges[:-1]): for j, yedge in enumerate(yedges[:-1]): rows.append(dict(high=yedge, low=xedge, count=hist[i, j])) df = pd.DataFrame(rows) ab = nt.sts[station]["archive_begin"] if ab is None: raise NoDataFound("Unknown station metadata.") years = float(datetime.datetime.now().year - ab.year) hist = np.ma.array(hist / years) hist.mask = np.where(hist < (1.0 / years), True, False) ar = np.argwhere(hist.max() == hist) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) res = ax.pcolormesh(xedges, yedges, hist.T) fig.colorbar(res, label="Days per Year") ax.grid(True) ax.set_title(("%s [%s]\n" "Daily High vs Low Temp Histogram (month=%s)") % (nt.sts[station]["name"], station, month.upper())) ax.set_ylabel(r"High Temperature $^{\circ}\mathrm{F}$") ax.set_xlabel(r"Low Temperature $^{\circ}\mathrm{F}$") xmax = ar[0][0] ymax = ar[0][1] ax.text( 0.65, 0.15, ("Largest Frequency: %.1f days\n" "High: %.0f-%.0f Low: %.0f-%.0f") % ( hist[xmax, ymax], yedges[ymax], yedges[ymax + 1], xedges[xmax], xedges[xmax + 1], ), ha="center", va="center", transform=ax.transAxes, bbox=dict(color="white"), ) ax.axhline(32, linestyle="-", lw=1, color="k") ax.text( 120, 32, r"32$^\circ$F", va="center", ha="right", color="white", bbox=dict(color="k"), fontsize=8, ) ax.axvline(32, linestyle="-", lw=1, color="k") ax.text( 32, 117, r"32$^\circ$F", va="top", ha="center", color="white", bbox=dict(facecolor="k", edgecolor="none"), fontsize=8, ) if year: label = str(year) if month == "winter": ddf["year"] = (ddf[((ddf["month"] == 1) | (ddf["month"] == 2))]["year"] - 1) label = "Dec %s - Feb %s" % (year, year + 1) ddf2 = ddf[ddf["year"] == year] ax.scatter( ddf2["low"], ddf2["high"], marker="x", label=label, edgecolor="white", facecolor="red", ) ax.legend() return fig, df
def main(): """Go Main Go.""" nt = network.Table("AWOS") qdict = loadqc() pgconn = get_dbconn("iem", user="******") icursor = pgconn.cursor() utc = datetime.datetime.utcnow() ets = utc.replace( tzinfo=pytz.utc, hour=0, minute=0, second=0, microsecond=0 ) sts12z = ets + datetime.timedelta(hours=-12) sts6z = ets + datetime.timedelta(hours=-18) sts24h = ets + datetime.timedelta(days=-1) fmt = "%-6s:%-19s: %3s / %3s / %5s / %4s / %2s\n" out = open("/tmp/awos_rtp.shef", "w") out.write( """ .BR DMX %s Z DH00/TAIRVS/TAIRVI/PPDRVZ/SFDRVZ/SDIRVZ : IOWA AWOS RTP FIRST GUESS PROCESSED BY THE IEM : 06Z TO 00Z HIGH TEMPERATURE FOR %s : 06Z TO 00Z LOW TEMPERATURE FOR %s : 00Z YESTERDAY TO 00Z TODAY RAINFALL : ...BASED ON REPORTED OBS... """ % ( ets.strftime("%m%d"), sts12z.strftime("%d %b %Y").upper(), sts12z.strftime("%d %b %Y").upper(), ) ) # We get 18 hour highs highs = {} sql = """SELECT t.id as station, round(max(tmpf)::numeric,0) as max_tmpf, count(tmpf) as obs FROM current_log c, stations t WHERE t.iemid = c.iemid and t.network = 'AWOS' and valid > %s and valid < %s and tmpf > -99 GROUP by t.id """ args = (sts6z, ets) icursor.execute(sql, args) for row in icursor: if qdict.get(row[0], {}).get("tmpf"): continue highs[row[0]] = row[1] # 00 UTC to 00 UTC Preciptation pcpn = {} icursor.execute( """ select id as station, sum(precip) from (select t.id, extract(hour from valid) as hour, max(phour) as precip from current_log c, stations t WHERE t.network = 'AWOS' and t.iemid = c.iemid and valid >= %s and valid < %s GROUP by t.id, hour) as foo GROUP by id""", (sts24h, ets), ) for row in icursor: if qdict.get(row[0], {}).get("precip") or row[1] is None: continue pcpn[row[0]] = "%5.2f" % (row[1],) lows = {} icursor.execute( """SELECT t.id as station, round(min(tmpf)::numeric,0) as min_tmpf, count(tmpf) as obs FROM current_log c, stations t WHERE t.iemid = c.iemid and t.network = 'AWOS' and valid > %s and valid < %s and tmpf > -99 GROUP by t,id""", (sts6z, ets), ) for row in icursor: if qdict.get(row[0], {}).get("tmpf"): continue lows[row[0]] = row[1] ids = list(nt.sts.keys()) ids.sort() for sid in ids: myP = pcpn.get(sid, "M") myH = highs.get(sid, "M") myL = lows.get(sid, "M") out.write(fmt % (sid, nt.sts[sid]["name"], myH, myL, myP, "M", "M")) out.write(".END\n") out.close() cmd = ( "pqinsert -p 'plot ac %s0000 awos_rtp_00z.shef " "awos_rtp_00z.shef shef' /tmp/awos_rtp.shef" ) % (ets.strftime("%Y%m%d"),) subprocess.call(cmd, shell=True)
def get_context(fdict): """ Get the context""" ctx = dict() pgconn = psycopg2.connect(database='coop', host='iemdb', user='******') station = fdict.get('station', 'IA0000') month = fdict.get('month', 7) ptype = fdict.get('type', 'max-high') threshold = int(fdict.get('threshold', -99)) table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) l = "0 days" if month == 'fall': months = [9, 10, 11] label = "Fall (SON)" elif month == 'winter': months = [12, 1, 2] l = "31 days" label = "Winter (DJF)" elif month == 'spring': months = [3, 4, 5] label = "Spring (MAM)" elif month == 'summer': months = [6, 7, 8] label = "Summer (JJA)" else: months = [int(month), ] label = calendar.month_name[int(month)] df = read_sql(""" WITH climo as (SELECT to_char(valid, 'mmdd') as sday, high, low from ncdc_climate81 WHERE station = %s) SELECT extract(year from day + '"""+l+"""'::interval)::int as myyear, max(o.high) as "max-high", min(o.high) as "min-high", avg(o.high) as "avg-high", max(o.low) as "max-low", min(o.low) as "min-low", avg(o.low) as "avg-low", max(o.precip) as "max-precip", sum(o.precip) as "sum-precip", sum(case when o.high >= %s then 1 else 0 end) as "days-high-above", sum(case when o.high < %s then 1 else 0 end) as "days-high-below", sum(case when o.high >= c.high then 1 else 0 end) as "days-high-above-avg", sum(case when o.low >= %s then 1 else 0 end) as "days-lows-above", sum(case when o.low < c.low then 1 else 0 end) as "days-lows-below-avg", sum(case when o.low < %s then 1 else 0 end) as "days-lows-below" from """+table+""" o JOIN climo c on (o.sday = c.sday) where station = %s and month in %s GROUP by myyear ORDER by myyear ASC """, pgconn, params=(nt.sts[station]['ncdc81'], threshold, threshold, threshold, threshold, station, tuple(months)), index_col='myyear') data = df[ptype].values ctx['data'] = data ctx['avgv'] = df[ptype].mean() ctx['df'] = df # Compute 30 year trailing average tavg = [None]*30 for i in range(30, len(data)): tavg.append(np.average(data[i-30:i])) ctx['tavg'] = tavg # End interval is inclusive ctx['a1981_2010'] = df.loc[1981:2010, ptype].mean() ctx['ptype'] = ptype ctx['station'] = station ctx['threshold'] = threshold ctx['month'] = month ctx['title'] = ("[%s] %s %s-%s" ) % (station, nt.sts[station]['name'], df.index.min(), df.index.max()) ctx['subtitle'] = ("%s %s" ) % (label, PDICT[ptype]) if ptype.find("days") == 0 and ptype.find('avg') == -1: ctx['subtitle'] += " (%s)" % (threshold,) units = "$^\circ$F" if ctx['ptype'].find('precip') > 0: units = "inches" elif ctx['ptype'].find('days') > 0: units = "days" ctx['ylabel'] = "%s [%s]" % (PDICT[ctx['ptype']], units) return ctx
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt import matplotlib.dates as mdates import matplotlib.colors as mpcolors pgconn = get_dbconn('coop') ccursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] year = ctx['year'] gdd1 = ctx['gdd1'] gdd2 = ctx['gdd2'] table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) ccursor.execute(""" SELECT day, gdd50(high,low) as gdd from """+table+""" WHERE year = %s and station = %s ORDER by day ASC """, (year, station)) days = [] gdds = [] for row in ccursor: gdds.append(float(row['gdd'])) days.append(row['day']) yticks = [] yticklabels = [] jan1 = datetime.datetime(year, 1, 1) for i in range(110, 330): ts = jan1 + datetime.timedelta(days=i) if ts.day == 1 or ts.day % 12 == 1: yticks.append(i) yticklabels.append(ts.strftime("%-d %b")) gdds = np.array(gdds) sts = datetime.datetime(year, 4, 1) ets = datetime.datetime(year, 6, 1) now = sts sz = len(gdds) days2 = [] starts = [] heights = [] success = [] rows = [] while now < ets: idx = int(now.strftime("%j")) - 1 running = 0 while idx < sz and running < gdd1: running += gdds[idx] idx += 1 idx0 = idx while idx < sz and running < gdd2: running += gdds[idx] idx += 1 success.append(running >= gdd2) idx1 = idx days2.append(now) starts.append(idx0) heights.append(idx1 - idx0) rows.append(dict(plant_date=now, start_doy=idx0, end_doy=idx1, success=success[-1])) now += datetime.timedelta(days=1) if True not in success: raise ValueError("No data, pick lower GDD values") df = pd.DataFrame(rows) heights = np.array(heights) success = np.array(success) starts = np.array(starts) cmap = plt.get_cmap('jet') bmin = min(heights[success]) - 1 bmax = max(heights[success]) + 1 bins = np.arange(bmin, bmax+1.1) norm = mpcolors.BoundaryNorm(bins, cmap.N) ax = plt.axes([0.125, 0.125, 0.75, 0.75]) bars = ax.bar(days2, heights, bottom=starts, fc='#EEEEEE') for i, mybar in enumerate(bars): if success[i]: mybar.set_facecolor(cmap(norm([heights[i]])[0])) ax.grid(True) ax.set_yticks(yticks) ax.set_yticklabels(yticklabels) ax.set_ylim(min(starts)-7, max(starts+heights)+7) ax.xaxis.set_major_formatter(mdates.DateFormatter('%-d\n%b')) ax.set_xlabel("Planting Date") ax.set_title(("%s [%s] %s GDD [base=50,ceil=86]\n" "Period between GDD %s and %s, gray bars incomplete" ) % (nt.sts[station]['name'], station, year, gdd1, gdd2)) ax2 = plt.axes([0.92, 0.1, 0.07, 0.8], frameon=False, yticks=[], xticks=[]) ax2.set_xlabel("Days") for i, mybin in enumerate(bins): ax2.text(0.52, i, "%g" % (mybin,), ha='left', va='center', color='k') # txt.set_path_effects([PathEffects.withStroke(linewidth=2, # foreground="k")]) ax2.barh(np.arange(len(bins[:-1])), [0.5]*len(bins[:-1]), height=1, color=cmap(norm(bins[:-1])), ec='None') ax2.set_xlim(0, 1) return plt.gcf(), df
def plotter(fdict): """ Go """ pgconn = get_dbconn("coop") ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] varname = ctx["var"] month = ctx["month"] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) yr = "year as yr" if month == "all": months = range(1, 13) elif month == "fall": months = [9, 10, 11] elif month == "winter": months = [12, 1, 2] yr = "extract(year from o.day - '60 days'::interval) as yr" elif month == "spring": months = [3, 4, 5] elif month == "summer": months = [6, 7, 8] else: ts = datetime.datetime.strptime("2000-" + month + "-01", "%Y-%b-%d") # make sure it is length two for the trick below in SQL months = [ts.month, 999] df = read_sql( """ WITH avgs as ( SELECT sday, avg(high) as avg_high, avg(low) as avg_low, avg((high+low)/2.) as avg_temp from """ + table + """ WHERE station = %s GROUP by sday) SELECT """ + yr + """, sum(case when o.high > a.avg_high then 1 else 0 end) as high_above, sum(case when o.low > a.avg_low then 1 else 0 end) as low_above, sum(case when (o.high+o.low)/2. > a.avg_temp then 1 else 0 end) as avg_above, count(*) as days from """ + table + """ o, avgs a WHERE o.station = %s and o.sday = a.sday and month in %s GROUP by yr ORDER by yr ASC """, pgconn, params=(station, station, tuple(months)), index_col="yr", ) if df.empty: raise NoDataFound("No Data Found.") df["high_freq"] = df["high_above"] / df["days"].astype("f") * 100.0 df["low_freq"] = df["low_above"] / df["days"].astype("f") * 100.0 df["avg_freq"] = df["avg_above"] / df["days"].astype("f") * 100.0 (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) avgv = df[varname + "_freq"].mean() colorabove = "r" colorbelow = "b" data = df[varname + "_freq"].values bars = ax.bar(df.index.values, data, fc=colorabove, ec=colorabove, align="center") for i, bar in enumerate(bars): if data[i] < avgv: bar.set_facecolor(colorbelow) bar.set_edgecolor(colorbelow) ax.axhline(avgv, lw=2, color="k", zorder=2) txt = ax.text( bars[10].get_x(), avgv, "Avg: %.1f%%" % (avgv, ), color="yellow", fontsize=14, va="center", ) txt.set_path_effects([PathEffects.withStroke(linewidth=5, foreground="k")]) ax.set_ylim(0, 100) ax.set_yticks([0, 10, 25, 50, 75, 90, 100]) ax.set_xlabel("Year") ax.set_xlim(bars[0].get_x() - 1, bars[-1].get_x() + 1) ax.set_ylabel("Frequency [%]") ax.grid(True) msg = ("[%s] %s %s-%s Percentage of Days with %s Above Average (month=%s)" ) % ( station, nt.sts[station]["name"], df.index.values.min(), df.index.values.max(), PDICT[varname], month.upper(), ) tokens = msg.split() sz = int(len(tokens) / 2) ax.set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] days = ctx['days'] sts = datetime.date(2012, ctx['month'], ctx['day']) ets = sts + datetime.timedelta(days=(days - 1)) varname = ctx['varname'] year = ctx['year'] threshold = ctx['thres'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) sdays = [] for i in range(days): ts = sts + datetime.timedelta(days=i) sdays.append(ts.strftime("%m%d")) doff = (days + 1) if ets.year != sts.year else 0 df = read_sql(""" SELECT extract(year from day - '""" + str(doff) + """ days'::interval) as yr, avg((high+low)/2.) as avg_temp, avg(high) as avg_high_temp, avg(low) as avg_low_temp, sum(precip) as precip, min(low) as min_low, max(high) as max_high, sum(case when high >= %s then 1 else 0 end) as "days-high-above", sum(case when high < %s then 1 else 0 end) as "days-high-below", sum(case when low >= %s then 1 else 0 end) as "days-lows-above", sum(case when low < %s then 1 else 0 end) as "days-lows-below" from """ + table + """ WHERE station = %s and sday in %s GROUP by yr ORDER by yr ASC """, pgconn, params=(threshold, threshold, threshold, threshold, station, tuple(sdays))) (fig, ax) = plt.subplots(2, 1, figsize=(8, 6)) bars = ax[0].bar(df['yr'], df[varname], facecolor='r', edgecolor='r') thisvalue = "M" for bar, x, y in zip(bars, df['yr'], df[varname]): if x == year: bar.set_facecolor('g') bar.set_edgecolor('g') thisvalue = y ax[0].set_xlabel("Year, %s = %s" % (year, nice(thisvalue))) ax[0].axhline(df[varname].mean(), lw=2, label='Avg: %.2f' % (df[varname].mean(), )) ylabel = r"Temperature $^\circ$F" if varname in [ 'precip', ]: ylabel = "Precipitation [inch]" elif varname.find('days') > -1: ylabel = "Days" ax[0].set_ylabel(ylabel) title = PDICT.get(varname).replace("(threshold)", str(threshold)) ax[0].set_title(("[%s] %s\n%s from %s through %s") % (station, nt.sts[station]['name'], title, sts.strftime("%d %b"), ets.strftime("%d %b")), fontsize=12) ax[0].grid(True) ax[0].legend(ncol=2, fontsize=10) ax[0].set_xlim(df['yr'].min() - 1, df['yr'].max() + 1) rng = df[varname].max() - df[varname].min() if varname == 'precip' or varname.startswith('days'): ax[0].set_ylim(-0.1, df[varname].max() + rng * .3) else: ax[0].set_ylim(df[varname].min() - rng * .3, df[varname].max() + rng * .3) box = ax[0].get_position() ax[0].set_position([box.x0, box.y0 + 0.02, box.width, box.height * 0.98]) # Plot 2: CDF X2 = np.sort(df[varname]) ptile = np.percentile(df[varname], [0, 5, 50, 95, 100]) N = len(df[varname]) F2 = np.array(range(N)) / float(N) * 100. ax[1].plot(X2, 100. - F2) ax[1].set_xlabel(ylabel) ax[1].set_ylabel("Observed Frequency [%]") ax[1].grid(True) ax[1].set_yticks([0, 5, 10, 25, 50, 75, 90, 95, 100]) mysort = df.sort_values(by=varname, ascending=True) info = ("Min: %.2f %.0f\n95th: %.2f\nMean: %.2f\nSTD: %.2f\n5th: %.2f\n" "Max: %.2f %.0f") % (df[varname].min(), df['yr'][mysort.index[0]], ptile[1], np.average(df[varname]), np.std(df[varname]), ptile[3], df[varname].max(), df['yr'][mysort.index[-1]]) ax[1].text(0.8, 0.95, info, transform=ax[1].transAxes, va='top', bbox=dict(facecolor='white', edgecolor='k')) return fig, df
def plotter(fdict): """ Go """ pgconn = get_dbconn("coop") ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] varname = ctx["var"] if PDICT.get(varname) is None: return table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) df = read_sql( """ with data as ( select extract(doy from day) as doy, day, """ + varname + """ as v from """ + table + """ WHERE station = %s), doyagg as ( SELECT doy, stddev(v) from data GROUP by doy), deltas as ( SELECT doy, (v - lag(v) OVER (ORDER by day ASC)) as d from data), deltaagg as ( SELECT doy, stddev(d) from deltas GROUP by doy) SELECT d.doy, d.stddev as d2d_stddev, y.stddev as doy_stddev from deltaagg d JOIN doyagg y ON (y.doy = d.doy) WHERE d.doy < 366 ORDER by d.doy ASC """, pgconn, params=(station, ), index_col="doy", ) fig, ax = plt.subplots(2, 1, sharex=True, figsize=(8, 6)) ax[0].plot(df.index.values, df["doy_stddev"], lw=2, color="r", label="Single Day") ax[0].plot(df.index.values, df["d2d_stddev"], lw=2, color="b", label="Day to Day") ax[0].legend(loc="best", fontsize=10, ncol=2) ax[0].set_ylabel(r"Temperature Std. Deviation $^\circ$F") ax[0].grid(True) msg = ("[%s] %s Daily %s Standard Deviations") % ( station, nt.sts[station]["name"], PDICT.get(varname), ) tokens = msg.split() sz = int(len(tokens) / 2) ax[0].set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) ax[1].plot(df.index.values, df["doy_stddev"] / df["d2d_stddev"], lw=2, color="g") ax[1].set_ylabel("Ratio SingleDay/Day2Day") ax[1].grid(True) ax[1].set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335)) ax[1].set_xticklabels(calendar.month_abbr[1:]) ax[1].set_xlim(0, 366) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt import matplotlib.dates as mdates pgconn = psycopg2.connect(database='coop', host='iemdb', user='******') station = fdict.get('station', 'IA0000') delta = fdict.get('delta', 'abs') year = int(fdict.get('year', datetime.date.today().year)) nt = network.Table("%sCLIMATE" % (station[:2], )) table = "alldata_%s" % (station[:2], ) df = read_sql(""" WITH days as ( select generate_series('%s-01-01'::date, '%s-12-31'::date, '1 day'::interval)::date as day, to_char(generate_series('%s-01-01'::date, '%s-12-31'::date, '1 day'::interval)::date, 'mmdd') as sday ), climo as ( SELECT sday, avg(high) as avg_high, stddev(high) as stddev_high, avg(low) as avg_low, stddev(low) as stddev_low from """ + table + """ WHERE station = %s GROUP by sday ), thisyear as ( SELECT day, sday, high, low from """ + table + """ WHERE station = %s and year = %s ), thisyear2 as ( SELECT d.day, d.sday, t.high, t.low from days d LEFT JOIN thisyear t on (d.sday = t.sday) ) SELECT t.day, t.sday, t.high, t.low, c.avg_high, c.avg_low, c.stddev_high, c.stddev_low from thisyear2 t JOIN climo c on (t.sday = c.sday) ORDER by t.day ASC """, pgconn, params=(year, year, year, year, station, station, year), index_col='day') df.index.name = 'Date' df['high_sigma'] = (df['high'] - df['avg_high']) / df['stddev_high'] df['low_sigma'] = (df['low'] - df['avg_low']) / df['stddev_low'] (fig, ax) = plt.subplots(2, 1, sharex=True) ax[0].plot(df.index, df.avg_high, color='r', linestyle='-', label='Climate High') ax[0].plot(df.index, df.avg_low, color='b', label='Climate Low') ax[0].set_ylabel(r"Temperature $^\circ\mathrm{F}$") ax[0].set_title("[%s] %s Climatology & %s Observations" % (station, nt.sts[station]['name'], year)) ax[0].plot(df.index, df.high, color='brown', label='%s High' % (year, )) ax[0].plot(df.index, df.low, color='green', label='%s Low' % (year, )) if delta == 'abs': ax[1].plot(df.index, df.high - df.avg_high, color='r', label='High Diff %s - Climate' % (year)) ax[1].plot(df.index, df.low - df.avg_low, color='b', label='Low Diff') ax[1].set_ylabel(r"Temp Difference $^\circ\mathrm{F}$") else: ax[1].plot(df.index, df.high_sigma, color='r', label='High Diff %s - Climate' % (year)) ax[1].plot(df.index, df.low_sigma, color='b', label='Low Diff') ax[1].set_ylabel(r"Temp Difference $\sigma$") ymax = max([df.high_sigma.abs().max(), df.low_sigma.abs().max()]) + 1 ax[1].set_ylim(0 - ymax, ymax) ax[1].legend(fontsize=10, ncol=2, loc='best') ax[1].grid(True) ax[0].legend(fontsize=10, ncol=2, loc=8) ax[0].grid() ax[0].xaxis.set_major_locator(mdates.MonthLocator(interval=1)) ax[0].xaxis.set_major_formatter(mdates.DateFormatter('%-d\n%b')) return fig, df
def plotter(fdict): """ Go """ pgconn = get_dbconn("coop") ctx = get_autoplot_context(fdict, get_description()) station = ctx["station"] month = ctx["month"] year = ctx["year"] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) df = read_sql( """ SELECT year, sum(precip) as total_precip, sum(gddxx(%s, %s, high::numeric,low::numeric)) as gdd from """ + table + """ WHERE station = %s and month = %s GROUP by year """, pgconn, params=(ctx["gddbase"], ctx["gddceil"], station, month), index_col="year", ) if len(df.index) < 3: raise NoDataFound("ERROR: No Data Found") gstats = df.gdd.describe() pstats = df.total_precip.describe() df["precip_sigma"] = (df.total_precip - pstats["mean"]) / pstats["std"] df["gdd_sigma"] = (df.gdd - gstats["mean"]) / gstats["std"] df["distance"] = (df.precip_sigma**2 + df.gdd_sigma**2)**0.5 h_slope, intercept, r_value, _, _ = stats.linregress( df["gdd_sigma"], df["precip_sigma"]) y1 = -4.0 * h_slope + intercept y2 = 4.0 * h_slope + intercept (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.set_position([0.1, 0.12, 0.8, 0.78]) ax.scatter(df["gdd_sigma"], df["precip_sigma"], label=None) ax.plot( [-4, 4], [y1, y2], label="Slope=%.2f R$^2$=%.2f" % (h_slope, r_value**2), ) xmax = df.gdd_sigma.abs().max() + 0.25 ymax = df.precip_sigma.abs().max() + 0.25 ax.set_xlim(0 - xmax, xmax) ax.set_ylim(0 - ymax, ymax) events = df.query("distance > 2.5 or year == %.0f" % (year, )) for _year, row in events.iterrows(): ax.text( row["gdd_sigma"], row["precip_sigma"], " %.0f" % (_year, ), va="center", ) if year in df.index: c = Circle((0, 0), radius=df.loc[year].distance, facecolor="none") ax.add_patch(c) ax.set_xlabel(("Growing Degree Day (base=%s, ceil=%s) " r"Departure ($\sigma$)") % (ctx["gddbase"], ctx["gddceil"])) ax.set_ylabel(r"Precipitation Departure ($\sigma$)") ax.grid(True) ax.set_title(("%s %s [%s]\n" "Growing Degree Day (base=%s, ceil=%s) " "+ Precipitation Departure") % ( calendar.month_name[month], nt.sts[station]["name"], station, ctx["gddbase"], ctx["gddceil"], )) ax.legend(loc="lower right", bbox_to_anchor=(1.05, 0.01), ncol=2, fontsize=10) return fig, df
def plotter(fdict): """ Go """ pgconn = get_dbconn('coop') ccursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] season = ctx['season'] _ = PDICT2[season] startyear = ctx['year'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) ccursor.execute( """ SELECT extract(year from day + '%s month'::interval) as yr, sum(case when month in (12, 1, 2) then precip else 0 end) as winter, sum(case when month in (3, 4, 5) then precip else 0 end) as spring, sum(case when month in (6, 7, 8) then precip else 0 end) as summer, sum(case when month in (9, 10, 11) then precip else 0 end) as fall, sum(precip) as all from """ + table + """ WHERE station = %s GROUP by yr ORDER by yr ASC """, (1 if season != 'all' else 0, station)) today = datetime.datetime.now() thisyear = today.year if season == 'spring' and today.month > 5: thisyear += 1 rows = [] for row in ccursor: if row['yr'] < startyear: continue rows.append(dict(year=int(row['yr']), data=float(row[season]))) df = pd.DataFrame(rows) data = np.array(df['data']) years = np.array(df['year']) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) avgv = np.average(data) colorabove = 'seagreen' colorbelow = 'lightsalmon' bars = ax.bar(years, data, fc=colorabove, ec=colorabove, align='center') for i, mybar in enumerate(bars): if data[i] < avgv: mybar.set_facecolor(colorbelow) mybar.set_edgecolor(colorbelow) ax.axhline(avgv, lw=2, color='k', zorder=2, label='Average') h_slope, intercept, r_value, _, _ = stats.linregress(years, data) ax.plot(years, h_slope * np.array(years) + intercept, '--', lw=2, color='k', label='Trend') ax.text(0.01, 0.99, "Avg: %.2f, slope: %.2f inch/century, R$^2$=%.2f" % (avgv, h_slope * 100., r_value**2), transform=ax.transAxes, va='top', bbox=dict(color='white')) ax.set_xlabel("Year") ax.set_xlim(min(years) - 1, max(years) + 1) ax.set_ylim(0, max(data) + max(data) / 10.) ax.set_ylabel("Precipitation [inches]") ax.grid(True) msg = ("[%s] %s %.0f-%.0f Precipitation [%s] ") % ( station, nt.sts[station]['name'], min(years), max(years), PDICT2[season]) tokens = msg.split() sz = int(len(tokens) / 2) ax.set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) ax.legend(ncol=2, fontsize=10) return fig, df
""" Generate a RTP product for the weather bureau as my database as more AWOS obs than what they get """ import datetime import pytz import os import subprocess from pyiem.tracker import loadqc from pyiem import network nt = network.Table("AWOS") qdict = loadqc() import psycopg2 IEM = psycopg2.connect(database='iem', host='iemdb', user='******') icursor = IEM.cursor() # We run at 12z now12z = datetime.datetime.utcnow() now12z = now12z.replace(hour=12, minute=0, second=0, microsecond=0, tzinfo=pytz.timezone("UTC")) today6z = now12z.replace(hour=6) today0z = now12z.replace(hour=0) yesterday6z = today6z - datetime.timedelta(days=1) yesterday12z = now12z - datetime.timedelta(days=1) fmt = "%-6s:%-19s: %3s / %3s / %5s / %4s / %2s\n"
def plotter(fdict): """ Go """ pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) today = datetime.datetime.now() thisyear = today.year df = read_sql(""" with data as ( select year, month, extract(doy from day) as doy, generate_series(32, high) as t from """ + table + """ where station = %s and year < %s), agger as ( SELECT year, t, min(doy), max(doy) from data GROUP by year, t) SELECT t as tmpf, avg(min) as min_jday, avg(max) as max_jday from agger GROUP by t ORDER by t ASC """, pgconn, params=(station, thisyear), index_col='tmpf') if df.empty: raise NoDataFound("No Data Found.") fig = plt.figure(figsize=(8, 6)) ax = plt.axes([0.1, 0.1, 0.7, 0.8]) ax2 = plt.axes([0.81, 0.1, 0.15, 0.8]) height = df['min_jday'][:] + 365. - df['max_jday'] ax2.plot(height, df.index.values) ax2.set_xticks([30, 90, 180, 365]) plt.setp(ax2.get_yticklabels(), visible=False) ax2.set_ylim(32, df.index.values.max() + 5) ax2.grid(True) ax2.text(0.96, 0.02, "Days", transform=ax2.transAxes, bbox=dict(color='white'), ha='right') ax.text(0.96, 0.02, "Period", transform=ax.transAxes, bbox=dict(color='white'), ha='right') ax.set_ylim(32, df.index.values.max() + 5) ax.barh(df.index.values - 0.5, height, left=df['max_jday'].values, ec='tan', fc='tan', height=1.1) days = np.array([1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335]) days = np.concatenate([days, days + 365]) ax.set_xticks(days) months = calendar.month_abbr[1:] + calendar.month_abbr[1:] ax.set_xticklabels(months) ax.set_ylabel("High Temperature $^\circ$F") ax.set_xlim(min(df['max_jday']) - 1, max(df['max_jday'] + height) + 1) ax.grid(True) msg = ("[%s] %s Period Between Average Last and " "First High Temperature of Year") % (station, nt.sts[station]['name']) tokens = msg.split() sz = int(len(tokens) / 2) ax.set_title(" ".join(tokens[:sz]) + "\n" + " ".join(tokens[sz:])) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt from matplotlib.patches import Circle pgconn = psycopg2.connect(database='coop', host='iemdb', user='******') station = fdict.get('station', 'IA0000') month = int(fdict.get('month', 7)) year = int(fdict.get('year', datetime.datetime.now().year)) table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) df = read_sql(""" SELECT year, sum(precip) as total_precip, sum(gdd50(high::numeric,low::numeric)) as gdd50 from """+table+""" WHERE station = %s and month = %s GROUP by year """, pgconn, params=(station, month), index_col='year') if len(df.index) == 0: return "ERROR: No Data Found" gstats = df.gdd50.describe() pstats = df.total_precip.describe() df['precip_sigma'] = (df.total_precip - pstats['mean']) / pstats['std'] df['gdd50_sigma'] = (df.gdd50 - gstats['mean']) / gstats['std'] df['distance'] = (df.precip_sigma ** 2 + df.gdd50_sigma ** 2) ** 0.5 h_slope, intercept, r_value, _, _ = stats.linregress(df['gdd50_sigma'], df['precip_sigma']) y1 = -4.0 * h_slope + intercept y2 = 4.0 * h_slope + intercept ax = plt.axes([0.1, 0.12, 0.8, 0.78]) ax.scatter(df['gdd50_sigma'], df['precip_sigma'], label=None) ax.plot([-4, 4], [y1, y2], label="Slope=%.2f\nR$^2$=%.2f" % (h_slope, r_value ** 2)) xmax = df.gdd50_sigma.abs().max() + 0.25 ymax = df.precip_sigma.abs().max() + 0.25 ax.set_xlim(0 - xmax, xmax) ax.set_ylim(0 - ymax, ymax) events = df.query("distance > 2.5 or year == %.0f" % (year, )) for _year, row in events.iterrows(): ax.text(row['gdd50_sigma'], row['precip_sigma'], ' %.0f' % (_year,), va='center') if year in df.index: c = Circle((0, 0), radius=df.loc[year].distance, facecolor='none') ax.add_patch(c) ax.set_xlabel("Growing Degree Day Departure ($\sigma$)") ax.set_ylabel("Precipitation Departure ($\sigma$)") ax.grid(True) ax.set_title(("%s %s [%s]\n" "Growing Degree Day (base=50) + Precipitation Departure" ) % ( calendar.month_name[month], nt.sts[station]['name'], station)) ax.legend(loc='upper right', bbox_to_anchor=(0.99, -0.04), ncol=2, fontsize=10) return plt.gcf(), df
def plotter(fdict): """ Go """ pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] season = ctx['season'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) df = read_sql(""" WITH obs as ( SELECT day, year, month, high, low, case when month > 6 then 'fall' else 'spring' end as season from """ + table + """ WHERE station = %s), data as ( SELECT year, day, season, max(high) OVER (PARTITION by year, season ORDER by day ASC ROWS BETWEEN 183 PRECEDING and CURRENT ROW) as mh, min(low) OVER (PARTITION by year, season ORDER by day ASC ROWS BETWEEN 183 PRECEDING and CURRENT ROW) as ml from obs), lows as ( SELECT year, day, ml as level, season, rank() OVER (PARTITION by year, ml ORDER by day ASC) from data WHERE season = 'fall'), highs as ( SELECT year, day, mh as level, season, rank() OVER (PARTITION by year, mh ORDER by day ASC) from data WHERE season = 'spring') (SELECT year, day, extract(doy from day) as doy, level, season from lows WHERE rank = 1) UNION (SELECT year, day, extract(doy from day) as doy, level, season from highs WHERE rank = 1) """, pgconn, params=[station]) df2 = df[df['season'] == season] (fig, ax) = plt.subplots(3, 1, figsize=(7, 10)) dyear = df2.groupby(['year']).count() ax[0].bar(dyear.index, dyear['level'], facecolor='tan', edgecolor='tan') ax[0].axhline(dyear['level'].mean(), lw=2) ax[0].set_ylabel("Yearly Events Avg: %.1f" % (dyear['level'].mean(), )) ax[0].set_xlim(dyear.index.min() - 1, dyear.index.max() + 1) title = "%s Steps %s" % (PDICT[season], "Down" if season == 'fall' else 'Up') ax[0].set_title("%s [%s]\n%s in Temperature" % (nt.sts[station]['name'], station, title)) ax[0].grid(True) ax[1].hist(np.array(df2['level'], 'f'), bins=np.arange(df2['level'].min(), df2['level'].max() + 1, 2), normed=True, facecolor='tan') ax[1].set_ylabel("Probability Density") ax[1].axvline(32, lw=2) ax[1].grid(True) ax[1].set_xlabel(r"Temperature $^\circ$F, 32 degrees highlighted") ax[2].hist(np.array(df2['doy'], 'f'), bins=np.arange(df2['doy'].min(), df2['doy'].max() + 1, 3), normed=True, facecolor='tan') ax[2].set_xticks( (1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365)) ax[2].set_xticklabels(calendar.month_abbr[1:]) ax[2].set_xlim(df2['doy'].min() - 3, df2['doy'].max() + 3) ax[2].set_ylabel("Probability Density") ax[2].grid(True) ax[2].set_xlabel("Day of Year, 3 Day Bins") return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] varname = ctx['var'] table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) tokens = varname.split("_") orderer = "(high - low)" if tokens[1] != 'range': orderer = tokens[1] if tokens[0] == 'min': orderer += " ASC" else: orderer += " DESC" df = read_sql(""" WITH ranks as ( SELECT month, day, high, low, precip, snow, rank() OVER (PARTITION by month ORDER by """ + orderer + """ NULLS LAST) from """ + table + """ WHERE station = %s) select month, to_char(day, 'Mon dd, YYYY') as dd, high, low, precip, snow, (high - low) as range from ranks WHERE rank = 1 ORDER by month ASC, day DESC """, pgconn, params=(station, ), index_col='month') labels = [] ranges = [] months = [] for i, row in df.iterrows(): if i in months: if labels[-1].endswith("*"): continue labels[-1] += " *" continue months.append(i) if tokens[1] == 'range': labels.append("%s (%s/%s) - %s" % (row[tokens[1]], row['high'], row['low'], row['dd'])) else: labels.append("%s - %s" % (row[tokens[1]], row['dd'])) ranges.append(row[tokens[1]]) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.barh(np.arange(1, 13), ranges, align='center') ax.set_yticklabels(calendar.month_name) ax.set_yticks(range(0, 13)) ax.set_ylim(0, 13) ax.set_xlabel(("Date most recently set/tied shown, " "* indicates ties are present")) fig.text(0.5, 0.99, "%s [%s]\n%s by Month" % (nt.sts[station]['name'], station, PDICT[varname]), transform=ax.transAxes, ha='center', fontsize=14, va='top') box = ax.get_position() ax.set_position([box.x0, box.y0, box.width * 0.7, box.height]) ax.grid(True) ax2 = ax.twinx() ax2.set_yticks(range(1, 13)) ax2.set_yticklabels(labels) ax2.set_position([box.x0, box.y0, box.width * 0.7, box.height]) ax2.set_ylim(0, 13) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = get_dbconn('coop') ctx = get_autoplot_context(fdict, get_description()) station = ctx['station'] threshold = ctx['thres'] use_trace = (ctx['trace'] == 'yes') table = "alldata_%s" % (station[:2],) nt = network.Table("%sCLIMATE" % (station[:2],)) df = read_sql(""" with data as ( select sday, day, precip from """ + table + """ where station = %s), rains as ( SELECT day from """ + table + """ WHERE station = %s and precip >= %s), rains2 as ( SELECT day from """ + table + """ WHERE station = %s and precip >= %s), agg as ( SELECT d.sday, d.day, d.precip, r.day as rday from data d LEFT JOIN rains r ON (d.day = r.day)), agg2 as ( SELECT d.sday, d.day, d.precip, d.rday, r.day as rday2 from agg d LEFT JOIN rains2 r ON (d.day = r.day)), agg3 as ( SELECT sday, precip, day - max(rday) OVER (ORDER by day ASC) as diff, day - max(rday2) OVER (ORDER by day ASC) as diff2 from agg2) SELECT sday, max(precip) as maxp, max(diff) as d1, max(diff2) as d2 from agg3 WHERE sday != '0229' GROUP by sday ORDER by sday ASC """, pgconn, params=(station, station, 0.0001 if use_trace else 0.01, station, threshold), index_col='sday') (fig, ax) = plt.subplots(2, 1, sharex=True) ax[0].plot(np.arange(1, 366), df['d1'], c='r', label='No Rain') ax[0].plot(np.arange(1, 366), df['d2'], c='b', label='Below %.2fin' % (threshold,)) ax[0].set_ylabel("Consec Days below threshold") ax[0].grid(True) ax[0].legend(ncol=2, loc=(0.5, -0.13), fontsize=10) ax[0].set_title("%s [%s] Precipitation Metrics" % (nt.sts[station]['name'], station)) ax[0].text(0.05, -0.09, "Trace Reports %s" % ('Included' if use_trace else 'Excluded',), transform=ax[0].transAxes, ha='left') ax[1].bar(np.arange(1, 366), df['maxp'], edgecolor='b', facecolor='b') ax[1].set_ylabel("Max 24 Hour Precip [inch]") ax[1].set_xlim(0.5, 366.5) ax[1].set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365)) ax[1].set_xticklabels(calendar.month_abbr[1:]) ax[1].grid(True) return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = psycopg2.connect(database='coop', host='iemdb', user='******') today = datetime.date.today() ctx = util.get_autoplot_context(fdict, get_description()) station = ctx['station'] threshold = ctx['threshold'] month1 = ctx['month1'] varname1 = ctx['var1'] num1 = min([12, ctx['num1']]) month2 = ctx['month2'] varname2 = ctx['var2'] num2 = min([12, ctx['num2']]) months1, offsets1 = compute_months_and_offsets(month1, num1) months2, offsets2 = compute_months_and_offsets(month2, num2) table = "alldata_%s" % (station[:2], ) nt = network.Table("%sCLIMATE" % (station[:2], )) # Compute the monthly totals df = read_sql(""" SELECT year, month, avg((high+low)/2.) as avg_temp, sum(precip) as total_precip, max(high) as max_high, sum(case when high >= %s then 1 else 0 end) as days_high_aoa, sum(gddxx(50, 86, high, low)) as gdd50 from """ + table + """ WHERE station = %s and day < %s GROUP by year, month """, pgconn, params=(threshold, station, today.replace(day=1)), index_col='year') xdf = combine(df, months1, offsets1) ydf = combine(df, months2, offsets2) resdf = pd.DataFrame({ "%s_1" % (varname1, ): xdf[varname1], "%s_2" % (varname2, ): ydf[varname2] }) resdf.dropna(inplace=True) (fig, ax) = plt.subplots(1, 1) ax.scatter(resdf[varname1 + "_1"], resdf[varname2 + "_2"], marker='s', facecolor='b', edgecolor='b', label=None, zorder=3) ax.set_title( ("%s-%s %s [%s]\n" "Comparison of Monthly Periods, Quadrant Frequency Labelled") % (resdf.index.min(), resdf.index.max(), nt.sts[station]['name'], station)) ax.grid(True) h_slope, intercept, r_value, _, _ = stats.linregress( resdf[varname1 + "_1"], resdf[varname2 + "_2"]) y = h_slope * np.arange(resdf[varname1 + "_1"].min(), resdf[varname1 + "_1"].max()) + intercept ax.plot(np.arange(resdf[varname1 + "_1"].min(), resdf[varname1 + "_1"].max()), y, lw=2, color='r', label="Slope=%.2f R$^2$=%.2f" % (h_slope, r_value**2)) ax.legend(fontsize=10) xmonths = ", ".join([calendar.month_abbr[x] for x in months1]) ymonths = ", ".join([calendar.month_abbr[x] for x in months2]) t1 = "" if varname1 not in [ 'days_high_aoa', ] else " %.0f" % (threshold, ) t2 = "" if varname2 not in [ 'days_high_aoa', ] else " %.0f" % (threshold, ) x = resdf["%s_1" % (varname1, )].mean() y = resdf["%s_2" % (varname2, )].mean() ax.set_xlabel("%s\n%s%s [%s], Avg: %.1f" % (xmonths, PDICT[varname1], t1, UNITS[varname1], x), fontsize=12) ax.set_ylabel("%s\n%s%s [%s], Avg: %.1f" % (ymonths, PDICT[varname2], t2, UNITS[varname2], y), fontsize=12) box = ax.get_position() ax.set_position( [box.x0, box.y0 + box.height * 0.05, box.width, box.height * 0.95]) ax.axhline(y, linestyle='--', color='g') ax.axvline(x, linestyle='--', color='g') ur = len(resdf[(resdf["%s_1" % (varname1, )] >= x) & (resdf["%s_2" % (varname2, )] >= y)].index) ax.text(0.95, 0.75, "%s (%.1f%%)" % (ur, ur / float(len(resdf.index)) * 100.), color='tan', fontsize=24, transform=ax.transAxes, ha='right', zorder=2) lr = len(resdf[(resdf["%s_1" % (varname1, )] >= x) & (resdf["%s_2" % (varname2, )] < y)].index) ax.text(0.95, 0.25, "%s (%.1f%%)" % (lr, lr / float(len(resdf.index)) * 100.), color='tan', fontsize=24, transform=ax.transAxes, ha='right', zorder=2) ll = len(resdf[(resdf["%s_1" % (varname1, )] < x) & (resdf["%s_2" % (varname2, )] < y)].index) ax.text(0.05, 0.25, "%s (%.1f%%)" % (ll, ll / float(len(resdf.index)) * 100.), color='tan', fontsize=24, transform=ax.transAxes, ha='left', zorder=2) ul = len(resdf[(resdf["%s_1" % (varname1, )] < x) & (resdf["%s_2" % (varname2, )] >= y)].index) ax.text(0.05, 0.75, "%s (%.1f%%)" % (ul, ul / float(len(resdf.index)) * 100.), color='tan', fontsize=24, transform=ax.transAxes, ha='left', zorder=2) return fig, resdf