This page demonstrates Python tips and tricks that I use in my everyday programming as an atmospheric science graduate student.
-Brian Blaylock

Showing posts with label MesoWest. Show all posts
Showing posts with label MesoWest. Show all posts

Friday, January 13, 2017

Wednesday, June 29, 2016

Plot a psudo-sounding with MesoWest Data

In the Salt Lake City area there are many weather stations at elevations higher than the valley floor. Farnsworth Peak is such a weather station at almost 700 hPa. I wondered what it would look like to plot station weather data on a skew-t graph, and see how it compares to rawinsonde balloons.

Here I use the MesoWest API and the Wyoming Sounding data to plot these graphs. I use the SkewT 1.1.0 module for Python to create the SkewT graph. The balloon observations are in green and the real observations are plotted in blue with the station id next to the point. A red line is drawn to create the "psudo-sounding" from the temperature observations at the different elevations. It doesn't match up exactly, except, for FWP, which seems to be an accurate representation of the temperatures of the atmosphere at that elevation.




## Brian Blaylock
## 27 June 2016

# A lot of the stations in Utah are at elevations.
# I want to plot station data on a skew-t graph to get a 
# psudo vertical profile for any time of day.

import matplotlib.pyplot as plt
import numpy as np
from datetime import datetime, timedelta

import sys
sys.path.append('B:\pyBKB')                                        #for running on PC (B:\ is my network drive)

from BB_MesoWest import MesoWest_stations_radius as MW
from skewt_900_700 import SkewT #this version plots between 900-700 hPa
import wyoming_sounding

##############################

request_time = datetime(2016,6,29,12,0)

##############################

MWdatetime = request_time.strftime('%Y%m%d%H%M')
a = MW.get_mesowest_radius_winds(MWdatetime,'10')

p = a['PRESS']>0 #pressure is in these indexes
pres = a['PRESS'][p]/100
temp = a['TEMP'][p]
hght = a['ELEVATION'][p]
dwpt = a['TEMP'][p]*np.nan #don't get the dewpoint now
wd   = a['WIND_DIR'][p]
ws   = a['WIND_SPEED'][p]
stns = a['STNID'][p]

# sort all that data based on pressure
from operator import itemgetter
pres,temp,hght,dwpt,wd,ws,stns = zip(*sorted(zip(pres,temp,hght,dwpt,wd,ws,stns),key=itemgetter(0)))



data = {'drct':wd,
        'dwpt':dwpt,        #don't plot dwpt right now
        'hght':hght,
        'pres':pres,
        'sknt':ws,
        'temp':temp}
S=SkewT.Sounding(soundingdata=data)

S.plot_skewt(title='psudo sounding\n'+MWdatetime,color='r',lw=.8,parcel_type=None,
             pmin=700.,pmax=900.)

for i in range(0,len(stns)):
    if temp[i]>0: #wont accept nan values
        print temp[i],pres[i],stns[i]
        S.plot_point(temp[i],pres[i])
        S.plot_text(temp[i],pres[i],str(stns[i]))
        
# Add real sounding to plot

# If request_time is in the afternoon, then request the evening sounding
if request_time.hour > 18:
    # Get the evening sounding (00 UTC) for the next day
    next_day = request_time + timedelta(days=1)
    request_sounding = datetime(next_day.year,next_day.month,next_day.day,0)    
elif request_time.hour < 6:
    # Get the evening sounding (00 UTC) for the same
    request_sounding = datetime(request_time.year,request_time.month,request_time.day,0)    
else:
    # Get the morning sounding (12 UTC) for the same day
    request_sounding = datetime(request_time.year,request_time.month,request_time.day,12)

print "SLC sounding for", request_sounding

a = wyoming_sounding.get_sounding(request_sounding)
balloon = {'drct':a['wdir'],
           #'dwpt':a['dwpt'],
           'hght':a['height'],
           'pres':a['press'],
           'sknt':a['wspd'],
           'temp':a['temp']}
# Add to plot
T = SkewT.Sounding(soundingdata=balloon)
S.soundingdata=T.soundingdata
S.add_profile(color='g',lw=.9,bloc=1.2)

             

Thursday, May 26, 2016

Spanish Fork Climatology

I just used the MesoWest API to create a climatology of weather variables at my weather station in Spanish Fork. This shows the max, mean, and min values for various variables of each month of the year. The data collected ranges from  2013 to 2016.

See code: https://github.com/blaylockbk/Ute_MesoWest/blob/master/station_month_climatology.py
The freezing temperature is marked in a dashed light blue.




And looking at the daily averages (again this is only a few years of data, so in no way an official "climatological" average of temperature on each day)

See code: https://github.com/blaylockbk/Ute_MesoWest/blob/master/station_day_climatology.py
We haven't had a day below freezing after the first few days of May.




Thursday, June 11, 2015

Python and MesoWest API

Uses the MesoWest API to get ozone concentration data and plot them. An example of formatting plot datetime plot tick marks is also shown.

# Brian Blaylock
# June 9, 2015

# Uses the MesoWest API to get find the maximum ozone
# from in-situ stations during GSLSO3S

# Tips for creating API request:
# -look at MesoWest API documentation: http://mesowest.org/api/docs/
# -use JSON viewer to see request results: http://jsonviewer.stack.hu/


import json
import numpy as np
import urllib2
import matplotlib.pyplot as plt
from datetime import datetime
from matplotlib.dates import DateFormatter, YearLocator, MonthLocator, DayLocator, HourLocator

token = '1234567890' #contact mesowest@lists.utah.edu to get your own token.

station = 'mtmet'
# dateformat YYYYMMDDHHMM
start_time = '201506050000'
end_time = '201506060000'
variables = 'ozone_concentration'
time_option = 'local'
URL = 'http://api.mesowest.net/v2/stations/timeseries?stid='+station+'&start='+start_time+'&end='+end_time+'&vars='+variables+'&obtimezone='+time_option+'&token='+token

#Open URL and read the content
f = urllib2.urlopen(URL)
data = f.read()

# convert that json string into some python readable format
data = json.loads(data)

stn_name = data['STATION'][0]['NAME']
# get ozone data convert to numpy array
ozone = data["STATION"][0]["OBSERVATIONS"]["ozone_concentration_set_1"]
#convert ozone into a numpy array: setting dtype=float replaces None value with a np.nan
ozone = np.array(ozone,dtype=float)

# get date and times and convert to datetime and put into a numpy array
dates = data["STATION"][0]["OBSERVATIONS"]["date_time"]
DATES = np.array([]) # first make an empty array
for i in dates:
   if time_option=='utc':
      converted_time = datetime.strptime(i,'%Y-%m-%dT%H:%M:%SZ')
   else:
      converted_time = datetime.strptime(i,'%Y-%m-%dT%H:%M:%S-0600')
   DATES = np.append(DATES,converted_time)


# make a simple ozone time series
#----------------------------------------------------------
ax = plt.subplot(1,1,1)
plt.plot(DATES,ozone)
plt.title('Ozone Concentration (ppb) for '+stn_name)
plt.xlabel('date')
plt.xticks(rotation=30)
#Now we format the date ticks
# Format Ticks
# Find months
months = MonthLocator()
# Find days
days = DayLocator()
# Find each 0 and 12 hours
hours = HourLocator(byhour=[0,6,12,18])
# Find all hours
hours_each = HourLocator()
# Tick label format style
dateFmt = DateFormatter('%b %d\n%H:%M')
# Set the x-axis major tick marks
ax.xaxis.set_major_locator(hours)
# Set the x-axis labels
ax.xaxis.set_major_formatter(dateFmt)
# For additional, unlabeled ticks, set x-axis minor axis
ax.xaxis.set_minor_locator(hours_each)


plt.savefig(start_time+'_'+end_time+'.png', format='png')