def test_windchill_basic(array_type): """Test the basic wind chill calculation.""" temp = array_type([40, -10, -45, 20], 'degF') speed = array_type([5, 55, 25, 15], 'mph') wc = windchill(temp, speed) values = array_type([36, -46, -84, 6], 'degF') assert_array_almost_equal(wc, values, 0)
def test_windchill_basic(): """Test the basic wind chill calculation.""" temp = np.array([40, -10, -45, 20]) * units.degF speed = np.array([5, 55, 25, 15]) * units.mph wc = windchill(temp, speed) values = np.array([36, -46, -84, 6]) * units.degF assert_array_almost_equal(wc, values, 0)
def test_windchill_undefined_flag(): """Test whether masking values for windchill can be disabled.""" temp = units.Quantity(np.ma.array([49, 50, 49, 60, 80, 81]), units.degF) speed = units.Quantity(([4, 4, 3, 1, 10, 39]), units.mph) wc = windchill(temp, speed, mask_undefined=False) mask = np.array([False] * 6) assert_array_equal(wc.mask, mask)
def test_windchill_face_level(): """Test windchill using the face_level flag.""" temp = np.array([20, 0, -20, -40]) * units.degF speed = np.array([15, 30, 45, 60]) * units.mph wc = windchill(temp, speed, face_level_winds=True) values = np.array([3, -30, -64, -98]) * units.degF assert_array_almost_equal(wc, values, 0)
def test_windchill_invalid(): """Test windchill for values that should be masked.""" temp = np.array([10, 51, 49, 60, 80, 81]) * units.degF speed = np.array([4, 4, 3, 1, 10, 39]) * units.mph wc = windchill(temp, speed) mask = np.array([False, True, True, True, True, True]) assert_array_equal(wc.mask, mask)
def test_windchill_invalid(): """Test windchill for values that should be masked.""" temp = np.array([10, 51, 49, 60, 80, 81]) * units.degF speed = np.array([4, 4, 3, 1, 10, 39]) * units.mph wc = windchill(temp, speed) # We don't care about the masked values truth = units.Quantity(np.ma.array([2.6230789, np.nan, np.nan, np.nan, np.nan, np.nan], mask=[False, True, True, True, True, True]), units.degF) assert_array_almost_equal(truth, wc)
def test_windchill_invalid(): """Test windchill for values that should be masked.""" temp = np.array([10, 51, 49, 60, 80, 81]) * units.degF speed = np.array([4, 4, 3, 1, 10, 39]) * units.mph wc = windchill(temp, speed) # We don't care about the masked values truth = np.array([2.6230789, np.nan, np.nan, np.nan, np.nan, np.nan]) * units.degF mask = np.array([False, True, True, True, True, True]) assert_array_almost_equal(truth, wc) assert_array_equal(wc.mask, mask)
def doday(ts, realtime): """ Create a plot of precipitation stage4 estimates for some day """ nt = NetworkTable(['AWOS', 'IA_ASOS']) pgconn = get_dbconn('iem', user='******') df = read_sql(""" SELECT id as station, tmpf, sknt from current_log c JOIN stations t on (c.iemid = t.iemid) WHERE t.network in ('IA_ASOS', 'AWOS') and valid >= %s and valid < %s + '24 hours'::interval and tmpf is not null and sknt > 0 """, pgconn, params=(ts, ts), index_col=None) df['wcht'] = windchill(df['tmpf'].values * units.degF, df['sknt'].values * units.knots).to(units.degF).magnitude gdf = df.groupby('station').min() routes = 'ac' if not realtime: routes = 'a' lons = [] lats = [] vals = [] labels = [] for station, row in gdf.iterrows(): lons.append(nt.sts[station]['lon']) lats.append(nt.sts[station]['lat']) vals.append(row['wcht']) labels.append(station) pqstr = ("plot %s %s00 summary/iowa_min_windchill.png " "summary/iowa_min_windchill.png png") % (routes, ts.strftime("%Y%m%d%H")) mp = MapPlot(title=(r"%s Minimum Wind Chill Temperature $^\circ$F") % (ts.strftime("%-d %b %Y"), ), subtitle="Calm conditions are excluded from analysis", continentalcolor='white') mp.plot_values(lons, lats, vals, '%.1f', labels=labels, textsize=12, labelbuffer=5, labeltextsize=10) mp.drawcounties() mp.postprocess(pqstr=pqstr, view=False) mp.close()
def main(argv): """Go Main Go.""" school = argv[1] req = requests.get( ('https://api.weather.gov/points/%s,%s/forecast/hourly' ) % (conf[school][2], conf[school][3])) jdata = req.json() rows = [] for data in jdata['properties']['periods']: ts = datetime.datetime.strptime(data['endTime'][:13], '%Y-%m-%dT%H') rows.append( dict(valid=ts, tmpf=data['temperature'], smph=int(data['windSpeed'].split()[0]))) df = pd.DataFrame(rows[:-24]) df['wcht'] = windchill( df['tmpf'].values * units('degF'), df['smph'].values * units('mph') ) (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.plot(df['valid'], df['wcht'], lw=2, color='g', label='Wind Chill') ax.plot(df['valid'], df['tmpf'], lw=2, color='r', label='Temperature') ax.set_ylabel(r"Temperature $^\circ$F") ax.set_title( ("NWS NDFD Grid Point Forecast for %s Airport" ) % (conf[school][4]) ) ax.grid(True) ax.legend(loc=1, ncol=2) ax.set_ylim(-60, 60) ax.set_yticks(range(-60, 61, 10)) ax2 = ax.twinx() ax2.scatter(df['valid'].values, df['smph'].values) ax2.set_ylim(0, 24) ax2.set_yticks(range(0, 25, 2)) ax2.set_ylabel("Wind Speed [mph], blue dots") ax2.xaxis.set_major_locator(mdates.HourLocator(byhour=[0, 12])) ax2.xaxis.set_major_formatter(mdates.DateFormatter('%-I %p\n%-d %b')) ax.axvspan( datetime.datetime(2019, 1, 29, 17), datetime.datetime(2019, 1, 31, 12), zorder=-1, color='tan') ax.text( datetime.datetime(2019, 1, 30, 14), -55, "%s CLOSED!" % (school, ), bbox=dict(color=conf[school][0]), ha='center', va='center', color=conf[school][1], fontsize=18 ) fig.savefig('%s.png' % (school, ))
def process(): """Go Main Go""" now = datetime.datetime(2019, 1, 29, 6) ets = datetime.datetime(2019, 2, 4, 6) interval = datetime.timedelta(hours=1) minval = None maxval = None while now < ets: fn = now.strftime(("/mesonet/ARCHIVE/data/%Y/%m/%d/" "model/rtma/%H/rtma.t%Hz.awp2p5f000.grib2" )) if not os.path.isfile(fn): print("missing %s" % (fn, )) else: grbs = None grbs = pygrib.open(fn) try: t2 = grbs.select(shortName='2t')[0].values u10 = grbs.select(shortName='10u')[0].values v10 = grbs.select(shortName='10v')[0].values except: print("FAIL!") now += interval continue smps = (u10 ** 2 + v10 ** 2) ** 0.5 wcht = windchill( t2 * units('degK'), smps * units('meter / second')) wcht = wcht.to(units('degF')).magnitude t2 = (t2 * units('degK')).to(units('degF')).magnitude if minval is None: minval = wcht maxval = (t2 * units('degK')).to(units('degF')).magnitude lats, lons = grbs.select(shortName='2t')[0].latlons() np.save('lons', lons) np.save('lats', lats) minval = np.where(wcht < minval, wcht, minval) maxval = np.where(t2 > maxval, t2, maxval) print("%s min: %.1f max: %.1f maxdel: %.1f" % ( now, np.min(minval), np.max(maxval), np.max(maxval - minval))) grbs.close() now += interval np.save('maxval', maxval) np.save('minval', minval)
def wind_chill(temperature, wind_speed): r"""This function calls the metpy method that calculates the wind chill. The arguments are pint Quantities that carry their units. The metpy method returns a wind chill with the units of degrees Fahrenheit. Args: temperature(pint.Quantity): atmospheric temperature. wind_speed(pint.Quantity): horizontal wind speed. Returns: wchill(pint.Quantity): wind chill in units of degree Fahrenheit. """ wchill = calc.windchill(temperature, wind_speed) return wchill
def mcalc_feelslike(tmpf, dwpf, smps): """Compute a feels like temperature Args: temperature (temperature): The dry bulb temperature dewpoint (temperature): The dew point temperature speed (speed): the wind speed Returns: temperature (temperature): The feels like temperature """ rh = mcalc.relative_humidity_from_dewpoint(tmpf, dwpf) hidx = mcalc.heat_index(tmpf, rh, mask_undefined=True) wcht = mcalc.windchill(tmpf, smps, mask_undefined=True) # Where heat index is masked, replace with temperature hidx[hidx.mask] = tmpf[hidx.mask] # where ever wcht is not masked, replace with wind chill hidx[~ wcht.mask] = wcht[~ wcht.mask] return hidx
def mcalc_feelslike(tmpf, dwpf, smps): """Compute a feels like temperature Args: temperature (temperature): The dry bulb temperature dewpoint (temperature): The dew point temperature speed (speed): the wind speed Returns: temperature (temperature): The feels like temperature """ rh = mcalc.relative_humidity_from_dewpoint(tmpf, dwpf) hidx = mcalc.heat_index(tmpf, rh, mask_undefined=True) wcht = mcalc.windchill(tmpf, smps, mask_undefined=True) # Where heat index is masked, replace with temperature hidx[hidx.mask] = tmpf[hidx.mask] # where ever wcht is not masked, replace with wind chill hidx[~wcht.mask] = wcht[~wcht.mask] return hidx
#Calculate dewpoint in F from relative humidity and temperature dewpt = C2F(dewpoint(data['TAIR'], data['RELH']/100.)) data = rec_append_fields(data, ('dewpoint',), (dewpt,)) #Convert temperature and dewpoint to Farenheit mod_units = mesonet_units.copy() mod_units['TAIR'] = 'F' mod_units['dewpoint'] = 'F' data['TAIR'] = C2F(data['TAIR']) #Convert wind speeds to MPH data['WSPD'] *= sconsts.hour / sconsts.mile data['WMAX'] *= sconsts.hour / sconsts.mile mod_units['WSPD'] = 'MPH' mod_units['WMAX'] = 'MPH' #Convert rainfall to inches data['RAIN'] *= sconsts.milli / sconsts.inch mod_units['RAIN'] = 'in.' #Calculate windchill wchill = windchill(data['TAIR'], data['WSPD'], metric=False) data = rec_append_fields(data, ('windchill',), (wchill,)) fig = plt.figure(figsize=(8,10)) layout = {0:['temperature', 'dewpoint', 'windchill']} axs = meteogram(data, fig, num_panels=5, units=mod_units, time_range=times, layout=layout) axs[0].set_ylabel('Temperature (F)') plt.show()
def plotter(fdict): """ Go """ pgconn = get_dbconn("asos") ctx = get_autoplot_context(fdict, get_description()) station = ctx["zstation"] highlightyear = ctx["year"] sdate = datetime.date(ctx["syear"], 1, 1) edate = datetime.date(ctx["eyear"] + 1, 1, 1) ytd = ctx["ytd"] varname = ctx["var"] inc = ctx["inc"] doylimiter = get_doylimit(ytd, varname) tmpflimit = "and tmpf >= 50" if varname != "windchill" else "and tmpf < 50" if varname not in ["windchill", "heatindex"]: tmpflimit = "" df = read_sql( "SELECT to_char(valid, 'YYYYmmddHH24') as d, avg(tmpf)::int as tmpf, " "avg(dwpf)::int as dwpf, avg(coalesce(sknt, 0)) as sknt " f"from alldata WHERE station = %s {tmpflimit} " "and dwpf <= tmpf and valid > %s and valid < %s and report_type = 2 " f"{doylimiter} GROUP by d", pgconn, params=(station, sdate, edate), index_col=None, ) if df.empty: raise NoDataFound("No Data Found.") df["year"] = df["d"].apply(lambda x: int(x[:4])) df2 = df title2 = VDICT[varname] compop = np.greater_equal inctitle = "" if varname == "heatindex": df["heatindex"] = (heat_index( df["tmpf"].values * units("degF"), relative_humidity_from_dewpoint( df["tmpf"].values * units("degF"), df["dwpf"].values * units("degF"), ), ).to(units("degF")).m) inctitle = " [All Obs Included]" if inc == "no": df2 = df[df["heatindex"] > df["tmpf"]] inctitle = " [Only Additive]" else: df2 = df maxval = int(df2["heatindex"].max() + 1) LEVELS[varname] = np.arange(80, maxval) elif varname == "windchill": compop = np.less_equal df["year"] = df["d"].apply(lambda x: (int(x[:4]) - 1) if int(x[4:6]) < 7 else int(x[:4])) df["windchill"] = (windchill( df["tmpf"].values * units("degF"), df["sknt"].values * units("knot"), ).to(units("degF")).m) inctitle = " [All Obs Included]" if inc == "no": df2 = df[df["windchill"] < df["tmpf"]] inctitle = " [Only Additive]" else: df2 = df minval = int(df2["windchill"].min() - 1) LEVELS[varname] = np.arange(minval, minval + 51) else: maxval = int(df2[varname].max() + 1) LEVELS[varname] = np.arange(maxval - 31, maxval) bs = ctx["_nt"].sts[station]["archive_begin"] if bs is None: raise NoDataFound("Unknown station metadata.") minyear = df["year"].min() maxyear = df["year"].max() years = float((maxyear - minyear) + 1) x = [] y = [] y2 = [] fig = plt.figure(figsize=(9, 6)) ax = fig.add_axes([0.1, 0.1, 0.6, 0.8]) yloc = 1.0 xloc = 1.13 yrlabel = ("%s" % (highlightyear, ) if varname != "windchill" else "%s-%s" % (highlightyear, highlightyear + 1)) ax.text(xloc + 0.08, yloc + 0.04, "Avg:", transform=ax.transAxes, color="b") ax.text(xloc + 0.21, yloc + 0.04, yrlabel, transform=ax.transAxes, color="r") df3 = df2[df2["year"] == highlightyear] for level in LEVELS[varname]: x.append(level) y.append(len(df2[compop(df2[varname], level)]) / years) y2.append(len(df3[compop(df3[varname], level)])) if level % 2 == 0: ax.text(xloc, yloc, "%s" % (level, ), transform=ax.transAxes) ax.text( xloc + 0.08, yloc, "%.1f" % (y[-1], ), transform=ax.transAxes, color="b", ) ax.text( xloc + 0.21, yloc, "%.0f" % (y2[-1], ), transform=ax.transAxes, color="r", ) yloc -= 0.04 ax.text(xloc, yloc, "n=%s" % (len(df2.index), ), transform=ax.transAxes) for x0, y0, y02 in zip(x, y, y2): ax.plot([x0, x0], [y0, y02], color="k") rdf = pd.DataFrame({"level": x, "avg": y, "d%s" % (highlightyear, ): y2}) x = np.array(x, dtype=np.float64) ax.scatter(x, y, color="b", label="Avg") ax.scatter(x, y2, color="r", label=yrlabel) ax.grid(True) ymax = int(max([max(y), max(y2)])) ax.set_xlim(x[0] - 0.5, x[-1] + 0.5) dy = 24 * (int(ymax / 240) + 1) ax.set_yticks(range(0, ymax, dy)) ax.set_ylim(-0.5, ymax + 5) ax2 = ax.twinx() ax2.set_ylim(-0.5, ymax + 5) ax2.set_yticks(range(0, ymax, dy)) ax2.set_yticklabels(["%.0f" % (s, ) for s in np.arange(0, ymax, dy) / 24]) ax2.set_ylabel("Expressed in 24 Hour Days") ax.set_ylabel("Hours Per Year") ax.set_xlabel(r"%s $^\circ$F" % (VDICT[varname], )) title = "till %s" % (datetime.date.today().strftime("%-d %b"), ) title = "Entire Year" if ytd == "no" else title ax.set_title(("[%s] %s %s-%s\n" "%s Histogram (%s)%s") % ( station, ctx["_nt"].sts[station]["name"], minyear, maxyear, title2, title, inctitle, )) ax.legend(loc="best", scatterpoints=1) return fig, rdf
def test_windchill_kelvin(): """Test wind chill when given Kelvin temperatures.""" wc = windchill(268.15 * units.kelvin, 35 * units('m/s')) assert_almost_equal(wc, -18.9357 * units.degC, 0)
def test_windchill_scalar(): """Test wind chill with scalars.""" wc = windchill(-5 * units.degC, 35 * units('m/s')) assert_almost_equal(wc, -18.9357 * units.degC, 0)
#Convert temperature and dewpoint to Farenheit mod_units = mesonet_units.copy() mod_units['TAIR'] = 'F' mod_units['dewpoint'] = 'F' data['TAIR'] = C2F(data['TAIR']) #Convert wind speeds to MPH data['WSPD'] *= sconsts.hour / sconsts.mile data['WMAX'] *= sconsts.hour / sconsts.mile mod_units['WSPD'] = 'MPH' mod_units['WMAX'] = 'MPH' #Convert rainfall to inches data['RAIN'] *= sconsts.milli / sconsts.inch mod_units['RAIN'] = 'in.' #Calculate windchill wchill = windchill(data['TAIR'], data['WSPD'], metric=False) data = rec_append_fields(data, ('windchill', ), (wchill, )) fig = plt.figure(figsize=(8, 10)) layout = {0: ['temperature', 'dewpoint', 'windchill']} axs = meteogram(data, fig, num_panels=5, units=mod_units, time_range=times, layout=layout) axs[0].set_ylabel('Temperature (F)') plt.show()