def mixing_ratio(_dewpoint): """Compute the mixing ratio Args: dewpoint (temperature): Dew Point temperature Returns: mixing ratio """ dwpc = _dewpoint.value("C") e = 6.112 * np.exp((17.67 * dwpc) / (dwpc + 243.5)) return dt.mixingratio(0.62197 * e / (1000.0 - e), "KG/KG")
def mixing_ratio(dewpoint): """Compute the mixing ratio Args: dewpoint (temperature): Dew Point temperature Returns: mixing ratio """ dwpc = dewpoint.value('C') e = 6.112 * np.exp((17.67 * dwpc) / (dwpc + 243.5)) return dt.mixingratio(0.62197 * e / (1000.0 - e), 'KG/KG')
def run_calcs(df): """Do our maths""" df['mixingratio'] = meteorology.mixing_ratio( temperature(df['dwpf'].values, 'F')).value('KG/KG') df['vapor_pressure'] = mcalc.vapor_pressure( 1000. * units.mbar, df['mixingratio'].values * units('kg/kg')).to(units('kPa')) df['saturation_mixingratio'] = (meteorology.mixing_ratio( temperature(df['tmpf'].values, 'F')).value('KG/KG')) df['saturation_vapor_pressure'] = mcalc.vapor_pressure( 1000. * units.mbar, df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa')) df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure'] group = df.groupby('year') df = group.aggregate(np.average) df['dwpf'] = meteorology.dewpoint_from_pq( pressure(1000, 'MB'), mixingratio(df['mixingratio'].values, 'KG/KG')).value('F') return df
def test_dewpoint_from_pq(self): """ See if we can produce dew point from pressure and mixing ratio """ p = datatypes.pressure(1013.25, "MB") mr = datatypes.mixingratio(0.012, "kg/kg") dwpk = meteorology.dewpoint_from_pq(p, mr) self.assertAlmostEqual(dwpk.value("C"), 16.84, 2)
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = psycopg2.connect(database='asos', host='iemdb', user='******') cursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['zstation'] network = ctx['network'] month = ctx['month'] nt = NetworkTable(network) 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] cursor.execute( """ SELECT drct::int as t, dwpf from alldata where station = %s and drct is not null and dwpf is not null and dwpf <= tmpf and sknt > 3 and drct::int %% 10 = 0 and extract(month from valid) in %s """, (station, tuple(months))) sums = np.zeros((361, ), 'f') counts = np.zeros((361, ), 'f') for row in cursor: r = mixing_ratio(temperature(row[1], 'F')).value('KG/KG') sums[row[0]] += r counts[row[0]] += 1 sums[0] = sums[360] counts[0] = counts[360] rows = [] for i in range(361): if counts[i] < 3: continue r = sums[i] / float(counts[i]) d = dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(r, 'KG/KG')).value('F') rows.append(dict(drct=i, dwpf=d)) df = pd.DataFrame(rows) drct = df['drct'] dwpf = df['dwpf'] (fig, ax) = plt.subplots(1, 1) ax.bar(drct, dwpf, ec='green', fc='green', width=10, align='center') ax.grid(True, zorder=11) ax.set_title(("%s [%s]\nAverage Dew Point by Wind Direction (month=%s) " "(%s-%s)\n" "(must have 3+ hourly obs > 3 knots at given direction)") % (nt.sts[station]['name'], station, month.upper(), max([1973, nt.sts[station]['archive_begin'].year ]), datetime.datetime.now().year), size=10) ax.set_ylabel("Dew Point [F]") ax.set_ylim(min(dwpf) - 5, max(dwpf) + 5) ax.set_xlim(-5, 365) ax.set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360]) ax.set_xticklabels(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N']) ax.set_xlabel("Wind Direction") return fig, df
def to_dwpf(val): return meteorology.dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(val, 'KG/KG') ).value('F')
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt ASOS = psycopg2.connect(database='asos', host='iemdb', user='******') cursor = ASOS.cursor(cursor_factory=psycopg2.extras.DictCursor) station = fdict.get('zstation', 'AMW') network = fdict.get('network', 'IA_ASOS') month = fdict.get('month', 'all') nt = NetworkTable(network) 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] cursor.execute(""" SELECT drct::int as t, dwpf from alldata where station = %s and drct is not null and dwpf is not null and dwpf <= tmpf and sknt > 3 and drct::int %% 10 = 0 and extract(month from valid) in %s """, (station, tuple(months))) sums = np.zeros((361,), 'f') counts = np.zeros((361,), 'f') for row in cursor: r = mixing_ratio(temperature(row[1], 'F')).value('KG/KG') sums[row[0]] += r counts[row[0]] += 1 sums[0] = sums[360] counts[0] = counts[360] rows = [] for i in range(361): if counts[i] < 3: continue r = sums[i] / float(counts[i]) d = dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(r, 'KG/KG') ).value('F') rows.append(dict(drct=i, dwpf=d)) df = pd.DataFrame(rows) drct = df['drct'] dwpf = df['dwpf'] (fig, ax) = plt.subplots(1, 1) ax.bar(drct-5, dwpf, ec='green', fc='green', width=10) ax.grid(True, zorder=11) ax.set_title(("%s [%s]\nAverage Dew Point by Wind Direction (month=%s) " "(%s-%s)\n" "(must have 3+ hourly obs > 3 knots at given direction)" ) % (nt.sts[station]['name'], station, month.upper(), max([1973, nt.sts[station]['archive_begin'].year]), datetime.datetime.now().year), size=10) ax.set_ylabel("Dew Point [F]") ax.set_ylim(min(dwpf)-5, max(dwpf)+5) ax.set_xlim(-5, 365) ax.set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360]) ax.set_xticklabels(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N']) ax.set_xlabel("Wind Direction") return fig, df
def test_mixingratio(self): """ Mixing Ratio""" mixr = datatypes.mixingratio(10, 'KG/KG') self.assertEquals(mixr.value('KG/KG'), 10)
def test_dewpoint_from_pq(): """ See if we can produce dew point from pressure and mixing ratio """ p = datatypes.pressure(1013.25, "MB") mr = datatypes.mixingratio(0.012, "kg/kg") dwpk = meteorology.dewpoint_from_pq(p, mr) assert abs(dwpk.value("C") - 16.84) < 0.01
def run_model(nc, initts, ncout, oldncout): """ Actually run the model, please """ t2 = nc.variables['t2'] u10 = nc.variables['u10'] v10 = nc.variables['v10'] tm = nc.variables['time'] lwdown = nc.variables['lwdown'] swdown = nc.variables['swdown'] q2 = nc.variables['q2'] rc = nc.variables['rain_con'] rn = nc.variables['rain_non'] lats = nc.variables['latitcrs'] lons = nc.variables['longicrs'] # keep masking in-tact as we only write data below when we have it otmpk = ma.array(ncout.variables['tmpk'][:]) otmpk._sharedmask = False owmps = ma.array(ncout.variables['wmps'][:]) owmps._sharedmask = False oswout = ma.array(ncout.variables['swout'][:]) oswout._sharedmask = False oh = ma.array(ncout.variables['h'][:]) oh._sharedmask = False olf = ma.array(ncout.variables['lf'][:]) olf._sharedmask = False obdeckt = ma.array(ncout.variables['bdeckt'][:]) obdeckt._sharedmask = False osubsfct = ma.array(ncout.variables['subsfct'][:]) osubsfct._sharedmask = False oifrost = ma.array(ncout.variables['ifrost'][:]) oifrost._sharedmask = False odwpk = ma.array(ncout.variables['dwpk'][:]) odwpk._sharedmask = False ofrostd = ma.array(ncout.variables['frostd'][:]) ofrostd._sharedmask = False oicond = ma.array(ncout.variables['icond'][:]) oicond._sharedmask = False # mini = 200 # minj = 200 # maxi = 0 # maxj = 0 errorcount = 0 cmd = "/usr/bin/python model/usr/bin/metro " cmd += "--roadcast-start-date %s " % (initts.strftime("%Y-%m-%dT%H:%MZ"),) cmd += "--input-forecast isumm5.xml " cmd += "--input-observation rwis.xml " cmd += "--input-station station.xml " cmd += "--output-roadcast roadcast.xml " cmd += "--log-file /dev/null " # cmd += "--verbose-level 4 " cmd += "--use-solarflux-forecast --use-infrared-forecast" # We don't have pressure from MM5 (yet) pressure = dt.pressure(1000.0, 'MB') for i in range(len(nc.dimensions['i_cross'])): if errorcount > 100: print('Too many errors, aborting....') sys.exit() # loopstart = datetime.datetime.now() for j in range(len(nc.dimensions['j_cross'])): lat = lats[i, j] lon = lons[i, j] # Hey, we only care about Iowa data! -97 40 -90 43.75 if lat < 40 or lat > 43.75 or lon < -97 or lon > -90: continue make_rwis(i, j, initts, oldncout) o = open('isumm5.xml', 'w') o.write("""<?xml version="1.0"?> <forecast> <header> <production-date>%s</production-date> <version>1.1</version> <filetype>forecast</filetype> <station-id>ofr</station-id> </header> <prediction-list>""" % ( datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%MZ"),)) for t in range(1, len(nc.dimensions['time'])): ts = initts + datetime.timedelta(minutes=int(tm[t])) tmpk = dt.temperature(t2[t, i, j], 'K') mr = dt.mixingratio(q2[t, i, j], 'KG/KG') dwp = met.dewpoint_from_pq(pressure, mr) sped = dt.speed((u10[t, i, j]**2 + v10[t, i, j]**2)**.5, 'MPS') # sn - snow accumulation in cm # ap - surface pressure in mb o.write("""<prediction> <forecast-time>%s</forecast-time> <at>%.1f</at> <td>%.1f</td> <ra>%.1f</ra> <sn>0.0</sn> <ws>%.1f</ws> <ap>993.8</ap> <wd>300</wd> <cc>0</cc> <sf>%.1f</sf> <ir>%.1f</ir> </prediction> """ % (ts.strftime("%Y-%m-%dT%H:%MZ"), tmpk.value("C"), dwp.value("C"), (rn[t, i, j] + rc[t, i, j])*10., sped.value("KMH"), swdown[t, i, j], lwdown[t, i, j]) ) o.write("</prediction-list></forecast>") o.close() proc = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) se = proc.stderr.read().decode("utf-8") if se != "": errorcount += 1 print(('metro error i:%03i j:%03i stderr:|%s|' ) % (i, j, se.strip())) continue # Starts at :20 minutes after start time tree = ET.parse('roadcast.xml') root = tree.getroot() tstep = 0 for c in root.findall('./prediction-list/prediction'): tstep += 1 # Road surface temperature st Celsius obdeckt[tstep, i, j] = float(c.find('./st').text) + 273.15 # Road sub surface temperature* (40 cm) sst Celsius osubsfct[tstep, i, j] = float(c.find('./sst').text) + 273.15 # Air temperature at Celsius otmpk[tstep, i, j] = float(c.find('./at').text) + 273.15 # Dew point td Celsius odwpk[tstep, i, j] = float(c.find('./td').text) + 273.15 # Wind speed ws km/h owmps[tstep, i, j] = float(c.find('./ws').text) # Quantity of snow or ice on the road sn cm # Quantity of rain on the road ra mm # Total (1 hr) snow precipitation qp-sn cm # Total (1 hr) rain precipitation qp-ra mm # Solar flux sf W/m2 oswout[tstep, i, j] = float(c.find('./sf').text) # Incident infra-red flux ir W/m2 # Vapor flux fv W/m2 # Sensible heat fc W/m2 # Anthropogenic flux fa W/m2 # Ground exchange flux fg W/m2 # Blackbody effect bb W/m2 # Phase change fp W/m2 # Road condition rc METRo code oicond[tstep, i, j] = int(c.find('./rc').text) # Octal cloud coverage** cc octal ncout.variables['tmpk'][:] = otmpk ncout.variables['wmps'][:] = dt.speed(owmps, 'KMH').value('MPS') ncout.variables['swout'][:] = oswout ncout.variables['h'][:] = oh ncout.variables['lf'][:] = olf ncout.variables['bdeckt'][:] = obdeckt ncout.variables['subsfct'][:] = osubsfct ncout.variables['ifrost'][:] = oifrost ncout.variables['frostd'][:] = ofrostd ncout.variables['dwpk'][:] = odwpk ncout.variables['icond'][:] = oicond
def to_dwpf(val): """Unsure why I am doing this, like this""" return meteorology.dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(val, 'KG/KG')).value('F')
def test_mixingratio(): """ Mixing Ratio""" mixr = datatypes.mixingratio(10, "KG/KG") assert mixr.value("KG/KG") == 10
def to_dwpf(val): return meteorology.dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(val, 'KG/KG')).value('F')
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = psycopg2.connect(database='asos', host='iemdb', user='******') cursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) station = fdict.get('zstation', 'AMW') network = fdict.get('network', 'IA_ASOS') month = fdict.get('month', 'all') nt = NetworkTable(network) 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] cursor.execute(""" SELECT tmpf::int as t, dwpf from alldata where station = %s and tmpf is not null and dwpf is not null and dwpf <= tmpf and tmpf >= 0 and tmpf <= 140 and extract(month from valid) in %s """, (station, tuple(months))) sums = np.zeros((140,), 'f') counts = np.zeros((140,), 'f') for row in cursor: r = mixing_ratio(temperature(row[1], 'F')).value('KG/KG') sums[row[0]] += r counts[row[0]] += 1 rows = [] for i in range(140): if counts[i] < 3: continue r = sums[i] / float(counts[i]) d = dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(r, 'KG/KG') ).value('F') rh = relh(temperature(i, 'F'), temperature(d, 'F')).value('%') rows.append(dict(tmpf=i, dwpf=d, rh=rh)) df = pd.DataFrame(rows) tmpf = df['tmpf'] dwpf = df['dwpf'] rh = df['rh'] (fig, ax) = plt.subplots(1, 1) ax.bar(tmpf-0.5, dwpf, ec='green', fc='green', width=1) ax.grid(True, zorder=11) ax.set_title(("%s [%s]\nAverage Dew Point by Air Temperature (month=%s) " "(%s-%s)\n" "(must have 3+ hourly observations at the given temperature)" ) % (nt.sts[station]['name'], station, month.upper(), nt.sts[station]['archive_begin'].year, datetime.datetime.now().year), size=10) ax.plot([0, 140], [0, 140], color='b') ax.set_ylabel("Dew Point [F]") y2 = ax.twinx() y2.plot(tmpf, rh, color='k') y2.set_ylabel("Relative Humidity [%] (black line)") y2.set_yticks([0, 5, 10, 25, 50, 75, 90, 95, 100]) y2.set_ylim(0, 100) ax.set_ylim(0, max(tmpf)+2) ax.set_xlim(0, max(tmpf)+2) ax.set_xlabel("Air Temperature $^\circ$F") return fig, df
def plotter(fdict): """ Go """ import matplotlib matplotlib.use('agg') import matplotlib.pyplot as plt pgconn = psycopg2.connect(database='asos', host='iemdb', user='******') cursor = pgconn.cursor(cursor_factory=psycopg2.extras.DictCursor) ctx = get_autoplot_context(fdict, get_description()) station = ctx['zstation'] network = ctx['network'] month = ctx['month'] nt = NetworkTable(network) 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] cursor.execute(""" SELECT tmpf::int as t, dwpf from alldata where station = %s and tmpf is not null and dwpf is not null and dwpf <= tmpf and tmpf >= 0 and tmpf <= 140 and extract(month from valid) in %s """, (station, tuple(months))) sums = np.zeros((140,), 'f') counts = np.zeros((140,), 'f') for row in cursor: r = mixing_ratio(temperature(row[1], 'F')).value('KG/KG') sums[row[0]] += r counts[row[0]] += 1 rows = [] for i in range(140): if counts[i] < 3: continue r = sums[i] / float(counts[i]) d = dewpoint_from_pq(pressure(1000, 'MB'), mixingratio(r, 'KG/KG') ).value('F') rh = relh(temperature(i, 'F'), temperature(d, 'F')).value('%') rows.append(dict(tmpf=i, dwpf=d, rh=rh)) df = pd.DataFrame(rows) tmpf = df['tmpf'] dwpf = df['dwpf'] rh = df['rh'] (fig, ax) = plt.subplots(1, 1, figsize=(8, 6)) ax.bar(tmpf-0.5, dwpf, ec='green', fc='green', width=1) ax.grid(True, zorder=11) ax.set_title(("%s [%s]\nAverage Dew Point by Air Temperature (month=%s) " "(%s-%s)\n" "(must have 3+ hourly observations at the given temperature)" ) % (nt.sts[station]['name'], station, month.upper(), nt.sts[station]['archive_begin'].year, datetime.datetime.now().year), size=10) ax.plot([0, 140], [0, 140], color='b') ax.set_ylabel("Dew Point [F]") y2 = ax.twinx() y2.plot(tmpf, rh, color='k') y2.set_ylabel("Relative Humidity [%] (black line)") y2.set_yticks([0, 5, 10, 25, 50, 75, 90, 95, 100]) y2.set_ylim(0, 100) ax.set_ylim(0, max(tmpf)+2) ax.set_xlim(0, max(tmpf)+2) ax.set_xlabel("Air Temperature $^\circ$F") return fig, df
def test_mixingratio(): """ Mixing Ratio""" mixr = datatypes.mixingratio(10, 'KG/KG') assert mixr.value('KG/KG') == 10