Example #1
0
     cb = figs[locName][0].colorbar(radar,
                                    cax=cax,
                                    orientation='horizontal')
     cb.set_label(
         'Simulated Radar Reflectivity (dBZ)\n\nBarbs: Half=2.5 m/s, Full=5 m/s, Flag=25 m/s'
     )
 #
 # Add nearby MesoWest
 MW_date = TS_temp['DATETIME'][hh]
 b = get_mesowest_radius(MW_date,
                         15,
                         extra='&radius=%s,%s,60' %
                         (l['latitude'], l['longitude']),
                         variables='wind_speed,wind_direction')
 if len(b['NAME']) > 0:
     MW_u, MW_v = wind_spddir_to_uv(b['wind_speed'],
                                    b['wind_direction'])
     MWx, MWy = maps[locName](b['LON'], b['LAT'])
     MW_barbs = figs[locName][1].barbs(MWx,
                                       MWy,
                                       MW_u,
                                       MW_v,
                                       color='r',
                                       barb_increments=dict(half=2.5,
                                                            full=5,
                                                            flag=25))
 #
 # Wind Barbs
 # Overlay wind barbs (need to trim this array before we plot it)
 # First need to trim the array
 barbs = figs[locName][1].barbs(trim_X,
                                trim_Y,
Example #2
0
# Get SLC sounding for Salt Lake City
balloon = get_wyoming_sounding(DATE)

# Get WRF from TS list profile data
station = 'KSLC'
wrf_dir = '/uufs/chpc.utah.edu/common/home/horel-group4/model/bblaylock/WRF3.8.1_MYNN/DATA/'
tsfile = station + '.d02.TS'
model_start = datetime(2015, 6, 14, 0)
wrf = get_vert_data(wrf_dir+tsfile,model_start,DATE)

# Get HRRR analysis profile from *modified* BUFR file 
# (modified so all data was on one row for easy reading)
hrrr_file = 'kslc_' + DATE.strftime('%Y%m%d%H') + '.txt'
HRRR = np.genfromtxt(hrrr_file, delimiter=' ', names=True)
HRRR_theta = TempPress_to_PotTemp(HRRR['TMPC'], HRRR['PRES'])
HRRR_u, HRRR_v = wind_calcs.wind_spddir_to_uv(HRRR['SKNT']*0.51444, HRRR['DRCT'])
HRRR_mixr = DwptPress_to_MixRatio(HRRR['DWPC'], HRRR['PRES'])

# Get HRRR 1-hour forecast
f = 'F01'
hrrr_file = 'kslc_'+datetime(2015,6,18,23).strftime('%Y%m%d%H')+'_'+f+'.txt'
HRRR_f01 = np.genfromtxt(hrrr_file, delimiter=' ', names=True)
HRRR_f01_theta = TempPress_to_PotTemp(HRRR_f01['TMPC'], HRRR_f01['PRES'])
HRRR_f01_u, HRRR_f01_v = wind_calcs.wind_spddir_to_uv(HRRR_f01['SKNT']*0.51444, HRRR_f01['DRCT'])
HRRR_f01_mixr = DwptPress_to_MixRatio(HRRR_f01['DWPC'], HRRR_f01['PRES'])

"""
Create 3 subplots for 
    1. Potential Temperature
    2. Mixing Ratio
    3. Vector Wind
Example #3
0
def plot_pm25_map(mobile,
                  other_mobile=False,
                  auto_map_boundaries=True,
                  background='WRF'):
    print "--plot map--"
    """
    makes a map of the helicopter observations. Also plots MesoWest
    input: mobile=ksl observations from the get moblie function
    
    other_mobile: if set to true will plot truck and trax data if available
    auto_map_boundaries: will find the location of the helicopter and will set auto boundaries
                         else, will map the salt lake valley or you can change the lat/lon manually
    background: 'WRF' will use a wrf file to contour the boundary
                'sat' will use an old satellite image
                'topo' will use a topographical image
    
    return: a string of the URL the figure is saved
    """
    plt.cla()
    plt.clf()
    plt.close()

    width = 4
    height = 4.5

    fig, (ax1) = plt.subplots(1, 1, figsize=(width, height))

    ## ---- Draw map
    top_right_lat = 40.9 + .1
    top_right_lon = -111.60
    bot_left_lat = 40.4 + .05
    bot_left_lon = -112.19785 - .05

    # Might need to make the map bigger if the chopper flew out of the valley
    try:
        if np.nanmax(mobile['latitude']) > top_right_lat:
            top_right_lat = np.nanmax(mobile['latitude']) + .01
        if np.nanmin(
                mobile['latitude'][mobile['latitude'] > -9999]) < bot_left_lat:
            bot_left_lat = np.nanmin(
                mobile['latitude'][mobile['latitude'] > -9999]) - .01
        if np.nanmax(mobile['longitude']) > top_right_lon:
            top_right_lon = np.nanmax(mobile['longitude']) + .01
        if np.nanmin(mobile['longitude'][
                mobile['longitude'] > -9999]) < bot_left_lon:
            bot_left_lon = np.nanmin(
                mobile['longitude'][mobile['longitude'] > -9999]) - .01
    except:
        # something funny with the lat/lon data not having a max or min
        # must have ozone or pm25 data but no lat lon data
        pass

    ## Map in cylindrical projection (data points may apear skewed)
    m = Basemap(resolution='i',projection='cyl',\
        llcrnrlon=bot_left_lon,llcrnrlat=bot_left_lat,\
        urcrnrlon=top_right_lon,urcrnrlat=top_right_lat,)

    # -----Set Background images

    if background == 'WRF':
        ## ---- Grab terrain data
        directory = '/uufs/chpc.utah.edu/common/home/horel-group4/model/bblaylock/WRF3.7_spinup/DATA/FULL_RUN_June14-19/'
        spat = 'auxhist23_d02_2015-06-14_00:00:00'
        nc_spatial = netcdf.netcdf_file(directory + spat, 'r')
        # This sets the standard grid point structure at full resolution
        #	Converts WRF lat and long to the maps x an y coordinate
        XLONG = nc_spatial.variables['XLONG'][0]
        XLAT = nc_spatial.variables['XLAT'][0]
        HGT = nc_spatial.variables['HGT'][0, :, :]  #topography
        landmask = nc_spatial.variables['LANDMASK'][0, :, :]

        # Plot Terrain
        X, Y = m(XLONG, XLAT)
        plt.contourf(X,
                     Y,
                     HGT,
                     levels=np.arange(1000, 4000, 500),
                     cmap='binary')
        # Draw major roads from shapefile
        m.readshapefile(
            '/uufs/chpc.utah.edu/common/home/u0553130/shape_files/tl_2015_UtahRoads_prisecroads/tl_2015_49_prisecroads',
            'roads',
            linewidth=.2)

        ## Contour Lake Outline
        plt.contour(X, Y, landmask, [0, 1], linewidths=1, colors="b")

    maps = [
        'ESRI_Imagery_World_2D',  # 0
        'ESRI_StreetMap_World_2D',  # 1
        'NatGeo_World_Map',  # 2
        'NGS_Topo_US_2D',  # 3
        'Ocean_Basemap',  # 4
        'USA_Topo_Maps',  # 5
        'World_Imagery',  # 6
        'World_Physical_Map',  # 7
        'World_Shaded_Relief',  # 8
        'World_Street_Map',  # 9
        'World_Terrain_Base',  # 10
        'World_Topo_Map'  # 11
    ]
    if background == 'sat':
        ## Instead of using WRF terrain fields you can get a high resolution image from ESRI
        m.arcgisimage(service=maps[0], xpixels=1000, verbose=True)
    if background == 'topo':
        ## Instead of using WRF terrain fields you can get a high resolution image from ESRI
        m.arcgisimage(service=maps[8], xpixels=1000, verbose=True)
        # Draw major roads from shapefile
        m.readshapefile(
            '/uufs/chpc.utah.edu/common/home/u0553130/shape_files/tl_2015_UtahRoads_prisecroads/tl_2015_49_prisecroads',
            'roads',
            linewidth=.2)
    # can use any other map background from maps list

    # Plot Other Mobile data
    if other_mobile == True:
        # Plot Mobile Ozone points (TRAX01)
        try:
            x, y = m(trax_mobile['longitude'], trax_mobile['latitude'])
            m.scatter(x[:],
                      y[:],
                      c=trax_mobile['pm25'][:],
                      vmax=45,
                      vmin=0.,
                      lw=.3,
                      marker='d',
                      s=30,
                      cmap=plt.cm.get_cmap('jet'),
                      zorder=50)
        except:
            print 'no TRAX01 data'

        # Plot Mobile Truck points (UUTK3)
        try:
            x, y = m(trk3_mobile['longitude'], trk3_mobile['latitude'])
            m.scatter(x[:],
                      y[:],
                      c=trk3_mobile['pm25'][:],
                      vmax=45,
                      vmin=0.,
                      lw=.3,
                      marker='p',
                      s=30,
                      cmap=plt.cm.get_cmap('jet'),
                      zorder=50)
        except:
            print 'no UUTK3 data'

        # Plot Mobile Truck points (UUTK1)
        try:
            x, y = m(trk1_mobile['longitude'], trk1_mobile['latitude'])
            m.scatter(x[:],
                      y[:],
                      c=trk1_mobile['pm25'][:],
                      vmax=45,
                      vmin=0.,
                      lw=.3,
                      marker='p',
                      s=30,
                      cmap=plt.cm.get_cmap('jet'),
                      zorder=50)
        except:
            print 'no UUTK1 data'

    ## Plot MesoWest  (top of the hour, +/- 10 mins)
    # Plot MesoWest wind data
    mesowest_time = str(request_time.year).zfill(2) + str(
        request_time.month).zfill(2) + str(request_time.day).zfill(2) + str(
            request_time.hour).zfill(2) + '00'
    print 'plotting mesowest observations within 10 minutes of top of the hour', mesowest_time, ' because the request time is:', request_time
    a = get_mesowest_radius(request_time, '10')
    u, v = wind_spddir_to_uv(a['wind_speed'], a['wind_direction'])
    m.barbs(a['LON'],
            a['LAT'],
            u,
            v,
            length=4.5,
            linewidth=.5,
            barb_increments=dict(half=1, full=2, flag=10),
            sizes=dict(spacing=0.15, height=0.3, emptybarb=.1))
    # ozone
    m.scatter(a['LON'],
              a['LAT'],
              c=a['pm25'],
              vmax=45,
              vmin=0.,
              lw=.3,
              s=20,
              marker='s',
              cmap=plt.cm.get_cmap('jet'),
              zorder=50)

    ## plot KSL on top of everything becuase it is flying
    # Plot Mobile Ozone points (KSL)
    x, y = m(mobile['longitude'], mobile['latitude'])
    # plot every 30 seconds rather than every 10 seconds (thus the [::3] indexes)
    m.scatter(x[::3],
              y[::3],
              c=ksl_mobile['pm25'][::3],
              vmax=45,
              vmin=0.,
              lw=.3,
              s=30,
              cmap=plt.cm.get_cmap('jet'),
              zorder=50)
    cbar = plt.colorbar(orientation='horizontal',
                        extend='both',
                        shrink=.8,
                        pad=.03)
    cbar.ax.set_xlabel('PM 2.5 (micrograms m-3)', fontsize=10)
    cbar.ax.tick_params(labelsize=8)
    cbar.set_ticks([0, 5, 10, 15, 20, 25, 30, 35, 40, 45])

    # Manually plot other Sensor locations by lat/lon
    """
    m.scatter(-111.93,40.9669, s=75, c='w',zorder=40)
    m.scatter(-112.01448,40.71152, s=75, c='b',zorder=40) # NAA
    m.scatter(-111.93072,40.95733, s=75, c='darkorange',zorder=40) # O3S02                        
    m.scatter(-111.828211,40.766573, s=75, c='r',zorder=40) # MTMET                       
    m.scatter(-111.8717,40.7335, s=75, c='darkgreen',zorder=40) # QHW               
    m.scatter(-111.96503,40.77069, s=75, c='w',zorder=40) # SLC               
    m.scatter(-112.34551,40.89068 , s=75, c='w',zorder=40) # GSLBY
    """

    ## Sidebar Text

    # is trax_in_yard, is trax available?
    if trax_mobile == 'No Data Available from TRX01 at this time':
        trax_time_range = 'n/a'
        trax_ozone_text = 'TRAX \n  n/a'
    else:
        trax_in_yard = ''
        if trax_mobile['longitude'].max() == -9999:
            trax_in_yard = '  -Yard-'
        trax_time_range = trax_mobile['DATES'][0].strftime(
            '%H:%M - ') + trax_mobile['DATES'][-1].strftime('%H:%M UTC')
        trax_ozone_text = 'TRAX' + trax_in_yard + '\n  Max:  %.2f ug m-3\n  Mean: %.2f ug m-3\n  Min:  %.2f ug m-3' % (
            np.nanmax(trax_mobile['pm25']),
            np.mean(trax_mobile['pm25'][trax_mobile['pm25'] > 0]),
            np.nanmin(trax_mobile['pm25']))

    obs_day = mobile['DATES'][-1].strftime('%d %b %Y')
    ksl_time_range = mobile['DATES'][0].strftime(
        '%H:%M - ') + mobile['DATES'][-1].strftime('%H:%M UTC')

    mesowest_time_range = datetime.strptime(mesowest_time,
                                            "%Y%m%d%H%M").strftime('%H:%M UTC')

    date_text = '%s\nKSL:  %s\nTRAX: %s\nMesoWest: %s' % (
        obs_day, ksl_time_range, trax_time_range, mesowest_time_range)
    ksl_ozone_text = 'KSL   \n  Max:  %.2f ug m-3\n  Mean: %.2f ug m-3\n  Min:  %.2f ug m-3' % (
        np.nanmax(mobile['pm25']), np.mean(
            mobile['pm25'][mobile['pm25'] > 0]), np.nanmin(mobile['pm25']))

    mesowest_ozone_text = ''
    for i in range(0, len(a['pm25'][a['pm25'] > 0])):
        station_obs = '%s: %.2f\n' % (a['STID'][a['pm25'] > 0][i],
                                      a['pm25'][a['pm25'] > 0][i])
        mesowest_ozone_text += station_obs
    all_text = date_text + '\n\n' + ksl_ozone_text + '\n\n' + trax_ozone_text + '\n\n' + mesowest_ozone_text
    fig.text(.93,
             .8,
             all_text,
             fontname='monospace',
             va='top',
             backgroundcolor='white',
             fontsize=7)

    plt.savefig(FIGDIR + string_time + '_KSL5_map_pm25.png',
                dpi=500,
                bbox_inches="tight")
    print 'saved map', FIGDIR + string_time + '_KSL5_map_pm25.png'
    print ""
    return 'http://home.chpc.utah.edu/~u0553130/oper/KSL_daily/' + string_time + '_KSL5_map_pm25.png\n'
Example #4
0
def get_wyoming_sounding(request_date, station='slc'):
    """
    June 13, 2016

    Download a sounding file from University of Wyoming Site and
    return a dictinary of the values

    Input:
        request_date - a datetime object in UTC. Hour must be either 0 or 12
        station - defaults to slc, the Salt Lake City. Alternativley use a
                  number for the station identier.

    Return:
        a dictionary of the data
    """

    if station == 'slc':
        stn = '72572'  # this is the id number for KSLC
    else:
        stn = str(station)

    year = str(request_date.year).zfill(4)
    month = str(request_date.month).zfill(2)
    day = str(request_date.day).zfill(2)
    # hour in UTC, 00 and 12 z usually available
    hour = str(request_date.hour).zfill(2)

    # Download, process and add to plot the Wyoming Data
    # 1)
    # Wyoming URL to download Sounding from
    url = 'http://weather.uwyo.edu/cgi-bin/sounding?' \
        + 'region=naconf&TYPE=TEXT%3ALIST' \
        + '&YEAR=' + year \
        + '&MONTH=' + month \
        + '&FROM=' + day + hour \
        + '&TO=' + day + hour \
        + '&STNM=' + stn
    content = urllib2.urlopen(url).read()

    # 2)
    # Remove the html tags
    soup = BeautifulSoup(content, "html.parser")
    data_text = soup.get_text()

    # 3)
    # Split the content by new line.
    splitted = data_text.split("\n", data_text.count("\n"))

    # 4)
    # Save the processed data as a .txt file to be read in by the skewt module.
    # See more here: https://pypi.python.org/pypi/SkewT
    Sounding_dir = './'
    Sounding_filename = str(stn) + '.' + str(year) + \
        str(month) + str(day) + str(hour) + '.txt'
    f = open(Sounding_dir + Sounding_filename, 'w')
    for line in splitted[4:]:
        f.write(line + '\n')
    f.close()

    # 5) Read the observed sounding file
    # Figure out where the footer is so we can skip it in np.genfromtxt
    # This is the line the data ends
    f = open(Sounding_filename, 'r')
    ls = f.readlines()
    f.close()

    header = 6  # There are at least six header rows
    data_in_row = [len(i.split()) for i in ls]
    for i in data_in_row[header:]:
        # Add a header row if 11 data points don't exist.
        if i != 11:
            header += 1
        else:
            break

    data_rows = 0  # count number of data rows
    for i in data_in_row[header:]:
        # as long as there are 11 data points in the row, add to data_rows
        if i == 11:
            data_rows += 1
        else:
            break

    # calculate number of lines in the footer
    last_line = len(ls)
    foot = last_line - header - data_rows

    sounding = np.genfromtxt(Sounding_filename,
                             skip_header=header,
                             skip_footer=foot)
    obs_press = sounding[:, 0]  # hPa
    obs_hght = sounding[:, 1]  # m
    obs_temp = sounding[:, 2]  # C
    obs_dwpt = sounding[:, 3]  # C
    obs_rh = sounding[:, 4]  # %
    obs_mixing = sounding[:, 5] / 1000  # kg/kg
    obs_wdir = sounding[:, 6]  # degrees
    obs_wspd = sounding[:, 7] * 0.51444  # m/s
    obs_theta = sounding[:, 8]  # K
    obs_u, obs_v = wind_calcs.wind_spddir_to_uv(obs_wspd, obs_wdir)  # m/s

    # 6)
    # Would be nice to return a diction of the station information from the
    # sounding file such as the Station identified, latitude, longitude,
    # calculated indexes, etc.

    data = {
        'url': url,  # URL the data is retrived from
        'file': Sounding_filename,  # Path to the file we created
        'DATE': request_date,  # Date requested (datetime object)
        'station': str(station),  # Requested station
        'press': obs_press,
        'height': obs_hght,
        'temp': obs_temp,
        'dwpt': obs_dwpt,
        'rh': obs_rh,
        'mixing ratio': obs_mixing,
        'wdir': obs_wdir,
        'wspd': obs_wspd,
        'theta': obs_theta,
        'u': obs_u,
        'v': obs_v
    }

    return data