def thetae( altimiter, tpc, tdc ): theta = thermo.theta( altimiter, tpc ) hpa = 33.8639 * altimiter tdk = tdc + 273.15 tpk = tpc + 273.15 func2 = ( -1*5420 )/tdk e = ( 2.53 * pow( 10,11 ) ) * np.exp( func2 ) e_hpa = e / 100 mixr = ( ( 0.622 * e_hpa )/( hpa - e_hpa ) ) thetae = theta*np.exp( ( ( 2.50 * pow( 10, 6 ) ) * mixr )/( 1005 * tpk ) ) return thetae
def thetae(altimiter, tpc, tdc): theta = thermo.theta(altimiter, tpc) hpa = 33.8639 * altimiter tdk = tdc + 273.15 tpk = tpc + 273.15 func2 = (-1 * 5420) / tdk e = (2.53 * pow(10, 11)) * np.exp(func2) e_hpa = e / 100 mixr = ((0.622 * e_hpa) / (hpa - e_hpa)) thetae = theta * np.exp(((2.50 * pow(10, 6)) * mixr) / (1005 * tpk)) return thetae
def make_skewT(tmin, tmax, pmax, pmin, skew=30.): #make a blank skewT diagram clf() #get a dense range of p, t0 to contour yplot = linspace(1050, 100, 100) xplot = linspace(-50, 50, 100) xplot, yplot = meshgrid(xplot, yplot) #lay down a reference grid that labels xplot,yplot points #in the new (skewT-lnP) coordinate system . # Each value of the temp matrix holds the actual (data) temperature # label (in deg C) of the xplot, yplot coordinate pairs #note that we don't have to transform the y coordinate #it's still the pressure #use the real (data) value to get the potential temperature T = xplot + skew*log(0.001*yplot) Tk = T + 273.15 #convert from C to K for use in thermo functios p = yplot*100. #convert from hPa to Pa th = thermo.theta(p, Tk) #theta labels #add the mixing ratio rstar = thermo.r_star(p, Tk) #wsat labels #saturated adiabat, so Tdew=Tk thetaeVals = thermo.theta_e(p, Tk, rstar, 0.) tempLabels = arange(-140., 50., 10.) con1 = contour(xplot, yplot, T, levels = tempLabels, colors = 'k', linewidths=.5) ax = gca() ax.set_yscale('log') lines = arange(100., 1100., 100.) yticks(lines, ['100','200','300','400','500','600','700','800','900','1000']) for line in lines: axhline(line, ls=':', color='k', linewidth=.5) thetaLabels = arange(200., 380., 10.) con2 = contour(xplot, yplot, th, levels = thetaLabels, colors='b', linewidths=.5) #rsLabels = [.1,.2,.4,.6, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 40] #con3 = contour(xplot, yplot, rstar*1.e3, levels=rsLabels, colors='g', linewidths=.5) #thetaeLabels = linspace(200,400,21) #con4 = contour(xplot, yplot, thetaeVals, levels = thetaeLabels, colors='r', linewidths=.5) axis([tmin, tmax, pmax, pmin]) clabel(con1, inline = False, fmt = '%1.0f') clabel(con2, inline = False, fmt = '%1.0f') #clabel(con3, inline = False, fmt = '%1.1f') #clabel(con4, inline = False, fmt = '%1.0f') title('skew T - lnp chart') ylabel('pressure (hPa)') xlabel('temperature (black, degrees C)')
def make_skewT(tmin, tmax, pmax, pmin, skew=30.): #make a blank skewT diagram clf() #get a dense range of p, t0 to contour yplot = linspace(1050, 100, 100) xplot = linspace(-50, 50, 100) xplot, yplot = meshgrid(xplot, yplot) #lay down a reference grid that labels xplot,yplot points #in the new (skewT-lnP) coordinate system . # Each value of the temp matrix holds the actual (data) temperature # label (in deg C) of the xplot, yplot coordinate pairs #note that we don't have to transform the y coordinate #it's still the pressure #use the real (data) value to get the potential temperature T = xplot + skew * log(0.001 * yplot) Tk = T + 273.15 #convert from C to K for use in thermo functios p = yplot * 100. #convert from hPa to Pa th = thermo.theta(p, Tk) #theta labels #add the mixing ratio rstar = thermo.r_star(p, Tk) #wsat labels #saturated adiabat, so Tdew=Tk thetaeVals = thermo.theta_e(p, Tk, rstar, 0.) tempLabels = arange(-140., 50., 10.) con1 = contour(xplot, yplot, T, levels=tempLabels, colors='k', linewidths=.5) ax = gca() ax.set_yscale('log') lines = arange(100., 1100., 100.) yticks(lines, [ '100', '200', '300', '400', '500', '600', '700', '800', '900', '1000' ]) for line in lines: axhline(line, ls=':', color='k', linewidth=.5) thetaLabels = arange(200., 380., 10.) con2 = contour(xplot, yplot, th, levels=thetaLabels, colors='b', linewidths=.5) rsLabels = [.1, .2, .4, .6, 1, 2, 3, 4, 5, 6, 8, 10, 15, 20, 25, 30, 40] con3 = contour(xplot, yplot, rstar * 1.e3, levels=rsLabels, colors='g', linewidths=.5) thetaeLabels = linspace(200, 400, 21) con4 = contour(xplot, yplot, thetaeVals, levels=thetaeLabels, colors='r', linewidths=.5) axis([tmin, tmax, pmax, pmin]) clabel(con1, inline=False, fmt='%1.0f') clabel(con2, inline=False, fmt='%1.0f') clabel(con3, inline=False, fmt='%1.1f') clabel(con4, inline=False, fmt='%1.0f') title('skew T - lnp chart') ylabel('pressure (hPa)') xlabel('temperature (black, degrees C)')
def Surface(self, **kwargs): ## Here begins the METAR decoder self.DatDict = {} ## this will serve as the intermediate dictionary for sorting self.RESULT = {} ## this is the result dictionary self.count = 0 ## will be used to tell us how many stations were not found stations = self.StationDict cycle = kwargs.get("cycle", self.cycle) file = urllib.urlopen("http://metfs1.agron.iastate.edu/data/text/sao/" + cycle + ".sao") text = ( file.read() .replace("\n", "") .replace("\x03", "") .replace("\x03\x01", "") .replace("\r", "") .strip() .split("=") ) ## process the text for line in text: if line.startswith("METAR"): line = line.strip("METAR") if ( line.startswith("K") == False and line.startswith("C") == False and line.startswith("M") == False and line.startswith("P") == False ): ## ignore lines with no metar station continue else: stn_key = line[:4] ## grab the station identifies, i.e. KBNA try: ## repeat observations are filtered by choosing the longest list of observations if len(self.DatDict[stn_key].split()) < len(line[4:].split()): self.DatDict[stn_key] = line[4:] except: ## if no observation, initialize it in the dictionary self.DatDict[stn_key] = line[4:] for stn in self.DatDict.keys(): if not stn in stations: self.count += 1 ## count the stations missing from the file continue stndat = self.DatDict[stn] if re.search("([0-9][0-9][0-9])([0-9][0-9])(G[0-9][0-9]KT)", stndat): ## These various regular expressions search for patterns ## that correspond with a certain type of data windat = re.search("([0-9][0-9][0-9])([0-9][0-9])(G[0-9][0-9]KT)", stndat).group() self.wdir = int(windat[:3]) self.wspd = int(windat[3:-5]) self.gust = int(windat[-4:-2]) elif re.search("([0-9][0-9][0-9])([0-9][0-9]KT)", stndat): windat = re.search("([0-9][0-9][0-9])([0-9][0-9])KT", stndat).group() self.wdir = int(windat[:3]) self.wspd = int(windat[3:-2]) self.gust = np.nan else: self.wdir = np.nan self.wspd = np.nan self.gust = np.nan if re.search( "\s(M[0-9][0-9])/(M[0-9][0-9])\s|\s([0-9][0-9])/(M[0-9][0-9])\s|\s(M[0-9][0-9])/(NIL)\s|\s([0-9][0-9])/(NIL)\s|\s([0-9][0-9])/([0-9][0-9])\s", stndat, ): self.tempdat = ( re.search( "\s(M[0-9][0-9])/(M[0-9][0-9])\s|\s([0-9][0-9])/(M[0-9][0-9])\s|\s(M[0-9][0-9])/(NIL)\s|\s([0-9][0-9])/(NIL)\s|\s([0-9][0-9])/([0-9][0-9])\s", stndat, ) .group() .replace("M", "-") .split("/") ) self.tempdat[0] = int(self.tempdat[0]) self.tempdat[1] = int(self.tempdat[1]) else: self.tempdat = [np.nan, np.nan] if re.search("SLP[0-9][0-9][0-9]", stndat): self.slpdat = re.search("SLP[0-9][0-9][0-9]", stndat).group().replace("SLP", "") if int(self.slpdat) <= 500: self.slpdat = 1000 + int(self.slpdat[:2]) + int(self.slpdat[2]) / 10 elif int(self.slpdat) > 500: self.slpdat = 900 + int(self.slpdat[:2]) + int(self.slpdat[2]) / 10 else: self.slpdat = np.nan if re.search("A[0-9][0-9][0-9][0-9]", stndat): self.altdat = re.search("A[0-9][0-9][0-9][0-9]", stndat).group().strip("A") self.altdat = int(self.altdat[:2]) + float(self.altdat[2:]) / 100 else: self.altdat = np.nan if re.search("[0-9][0-9]SM|[0-9]SM", stndat): self.vis = re.search("[0-9][0-9]SM|[0-9]SM", stndat).group().replace("SM", "") else: self.vis = np.nan if re.search("\s(P[0-9][0-9][0-9][0-9])", stndat): self.precip = re.search("\s(P[0-9][0-9][0-9][0-9])", stndat).group().replace("P", "") self.precip = float(str(self.precip)[:2] + "." + str(self.precip)[3:]) else: self.precip = np.nan self.RESULT[stn] = {} self.RESULT[stn]["TMPC"] = self.tempdat[0] self.RESULT[stn]["TMPF"] = self.tempdat[0] * 1.8 + 32 self.RESULT[stn]["DWPC"] = self.tempdat[1] self.RESULT[stn]["DWPF"] = self.tempdat[1] * 1.8 + 32 self.RESULT[stn]["THTA"] = therm.theta(self.altdat, self.tempdat[0]) self.RESULT[stn]["MIXR"] = therm.mixingratio(self.altdat, self.tempdat[0], self.tempdat[1]) self.RESULT[stn]["THTE"] = therm.thetae(self.altdat, self.tempdat[0], self.tempdat[1]) self.RESULT[stn]["RELH"] = therm.relhumid(self.tempdat[0], self.tempdat[1]) self.RESULT[stn]["WDIR"] = self.wdir self.RESULT[stn]["WSPD"] = self.wspd self.RESULT[stn]["GUST"] = self.gust self.RESULT[stn]["VWIN"] = vect.VWIN(self.wdir, self.wspd) self.RESULT[stn]["UWIN"] = vect.UWIN(self.wdir, self.wspd) self.RESULT[stn]["UMET"] = vect.UMET(self.wdir, self.wspd) self.RESULT[stn]["VMET"] = vect.VMET(self.wdir, self.wspd) self.RESULT[stn]["PRES"] = self.slpdat self.RESULT[stn]["ALTI"] = self.altdat self.RESULT[stn]["VISI"] = self.vis self.RESULT[stn]["PCPN"] = self.precip file.close() return self.RESULT
def Surface(self, **kwargs): ## Here begins the METAR decoder self.DatDict = { } ## this will serve as the intermediate dictionary for sorting self.RESULT = {} ## this is the result dictionary self.count = 0 ## will be used to tell us how many stations were not found stations = self.StationDict cycle = kwargs.get('cycle', self.cycle) file = urllib.urlopen( 'http://metfs1.agron.iastate.edu/data/text/sao/' + cycle + '.sao') text = file.read().replace('\n', '').replace('\x03', '').replace( '\x03\x01', '').replace('\r', '').strip().split('=') ## process the text for line in text: if line.startswith('METAR'): line = line.strip('METAR') if line.startswith('K') == False and line.startswith( 'C' ) == False and line.startswith('M') == False and line.startswith( 'P') == False: ## ignore lines with no metar station continue else: stn_key = line[:4] ## grab the station identifies, i.e. KBNA try: ## repeat observations are filtered by choosing the longest list of observations if len(self.DatDict[stn_key].split()) < len( line[4:].split()): self.DatDict[stn_key] = line[4:] except: ## if no observation, initialize it in the dictionary self.DatDict[stn_key] = line[4:] for stn in self.DatDict.keys(): if not stn in stations: self.count += 1 ## count the stations missing from the file continue stndat = self.DatDict[stn] if re.search('([0-9][0-9][0-9])([0-9][0-9])(G[0-9][0-9]KT)', stndat): ## These various regular expressions search for patterns ## that correspond with a certain type of data windat = re.search( '([0-9][0-9][0-9])([0-9][0-9])(G[0-9][0-9]KT)', stndat).group() self.wdir = int(windat[:3]) self.wspd = int(windat[3:-5]) self.gust = int(windat[-4:-2]) elif re.search('([0-9][0-9][0-9])([0-9][0-9]KT)', stndat): windat = re.search('([0-9][0-9][0-9])([0-9][0-9])KT', stndat).group() self.wdir = int(windat[:3]) self.wspd = int(windat[3:-2]) self.gust = np.nan else: self.wdir = np.nan self.wspd = np.nan self.gust = np.nan if re.search( '\s(M[0-9][0-9])/(M[0-9][0-9])\s|\s([0-9][0-9])/(M[0-9][0-9])\s|\s(M[0-9][0-9])/(NIL)\s|\s([0-9][0-9])/(NIL)\s|\s([0-9][0-9])/([0-9][0-9])\s', stndat): self.tempdat = re.search( '\s(M[0-9][0-9])/(M[0-9][0-9])\s|\s([0-9][0-9])/(M[0-9][0-9])\s|\s(M[0-9][0-9])/(NIL)\s|\s([0-9][0-9])/(NIL)\s|\s([0-9][0-9])/([0-9][0-9])\s', stndat).group().replace('M', '-').split('/') self.tempdat[0] = int(self.tempdat[0]) self.tempdat[1] = int(self.tempdat[1]) else: self.tempdat = [np.nan, np.nan] if re.search('SLP[0-9][0-9][0-9]', stndat): self.slpdat = re.search('SLP[0-9][0-9][0-9]', stndat).group().replace('SLP', '') if int(self.slpdat) <= 500: self.slpdat = 1000 + int( self.slpdat[:2]) + int(self.slpdat[2]) / 10 elif int(self.slpdat) > 500: self.slpdat = 900 + int( self.slpdat[:2]) + int(self.slpdat[2]) / 10 else: self.slpdat = np.nan if re.search('A[0-9][0-9][0-9][0-9]', stndat): self.altdat = re.search('A[0-9][0-9][0-9][0-9]', stndat).group().strip('A') self.altdat = int( self.altdat[:2]) + float(self.altdat[2:]) / 100 else: self.altdat = np.nan if re.search('[0-9][0-9]SM|[0-9]SM', stndat): self.vis = re.search('[0-9][0-9]SM|[0-9]SM', stndat).group().replace('SM', '') else: self.vis = np.nan if re.search('\s(P[0-9][0-9][0-9][0-9])', stndat): self.precip = re.search('\s(P[0-9][0-9][0-9][0-9])', stndat).group().replace('P', '') self.precip = float( str(self.precip)[:2] + '.' + str(self.precip)[3:]) else: self.precip = np.nan self.RESULT[stn] = {} self.RESULT[stn]['TMPC'] = self.tempdat[0] self.RESULT[stn]['TMPF'] = self.tempdat[0] * 1.8 + 32 self.RESULT[stn]['DWPC'] = self.tempdat[1] self.RESULT[stn]['DWPF'] = self.tempdat[1] * 1.8 + 32 self.RESULT[stn]['THTA'] = therm.theta(self.altdat, self.tempdat[0]) self.RESULT[stn]['MIXR'] = therm.mixingratio( self.altdat, self.tempdat[0], self.tempdat[1]) self.RESULT[stn]['THTE'] = therm.thetae(self.altdat, self.tempdat[0], self.tempdat[1]) self.RESULT[stn]['RELH'] = therm.relhumid(self.tempdat[0], self.tempdat[1]) self.RESULT[stn]['WDIR'] = self.wdir self.RESULT[stn]['WSPD'] = self.wspd self.RESULT[stn]['GUST'] = self.gust self.RESULT[stn]['VWIN'] = vect.VWIN(self.wdir, self.wspd) self.RESULT[stn]['UWIN'] = vect.UWIN(self.wdir, self.wspd) self.RESULT[stn]['UMET'] = vect.UMET(self.wdir, self.wspd) self.RESULT[stn]['VMET'] = vect.VMET(self.wdir, self.wspd) self.RESULT[stn]['PRES'] = self.slpdat self.RESULT[stn]['ALTI'] = self.altdat self.RESULT[stn]['VISI'] = self.vis self.RESULT[stn]['PCPN'] = self.precip file.close() return self.RESULT