Beispiel #1
1
def test_speed_dir_roundtrip():
    """Test round-tripping between speed/direction and components."""
    # Test each quadrant of the whole circle
    wspd = np.array([15., 5., 2., 10.]) * units.meters / units.seconds
    wdir = np.array([160., 30., 225., 350.]) * units.degrees

    u, v = get_wind_components(wspd, wdir)

    wdir_out = get_wind_dir(u, v)
    wspd_out = get_wind_speed(u, v)

    assert_array_almost_equal(wspd, wspd_out, 4)
    assert_array_almost_equal(wdir, wdir_out, 4)
Beispiel #2
1
def test_wind_comps_basic():
    """Test the basic wind component calculation."""
    speed = np.array([4, 4, 4, 4, 25, 25, 25, 25, 10.]) * units.mph
    dirs = np.array([0, 45, 90, 135, 180, 225, 270, 315, 360]) * units.deg
    s2 = np.sqrt(2.)

    u, v = get_wind_components(speed, dirs)

    true_u = np.array([0, -4 / s2, -4, -4 / s2, 0, 25 / s2, 25, 25 / s2, 0]) * units.mph
    true_v = np.array([-4, -4 / s2, 0, 4 / s2, 25, 25 / s2, 0, -25 / s2, -10]) * units.mph

    assert_array_almost_equal(true_u, u, 4)
    assert_array_almost_equal(true_v, v, 4)
def plot_sounding(sndg_data, yr, day, mo, hr, diablo_sounding):
    plt.rcParams['figure.figsize'] = (9, 9)
    skew_evening = SkewT()
    one_sounding = sndg_data.loc[sndg_data[' Hour'] == hr]
    T = convert_temperature(one_sounding[' Temp'].values, 'F', 'C')
    rh = one_sounding[' RH'].values
    one_sounding[' Dewpt'] = calc_dewpt(T, rh)
    one_sounding = one_sounding.dropna(subset=(' Temp', ' Dewpt'),
                                       how='all').reset_index(drop=True)

    T = convert_temperature(one_sounding[' Temp'].values, 'F',
                            'C') * units.degC
    p = one_sounding[' Pres'].values * units.hPa
    Td = one_sounding[' Dewpt'].values * units.degC
    wind_speed = one_sounding[' Spd'].values * units.knots
    wind_dir = one_sounding[' Dir '].values * units.degrees
    u, v = mpcalc.get_wind_components(wind_speed, wind_dir)
    skew_evening.plot(p, T, 'r')
    skew_evening.plot(p, Td, 'g')
    skew_evening.plot_barbs(p, u, v)
    skew_evening.plot_dry_adiabats()
    skew_evening.plot_moist_adiabats()
    skew_evening.plot_mixing_lines()
    skew_evening.ax.set_ylim(1000, 100)
    plt.title('OAK Sounding: ' + str(int(mo)) + '/' + str(int(day)) + '/' +
              str(int(yr)) + ': ' + str(int(hr)) + ' UTC')
    plt.savefig('../Images/20180703/' + diablo_sounding +
                '/OAK_sounding_eve_' + str(int(mo)) + '_' + str(int(day)) +
                '_' + str(int(yr)) + '_' + str(int(hr)) + 'UTC.png')
    plt.close()
    return one_sounding
Beispiel #4
0
def getMesoData(procYear, procMonth, procDay, procStation):
	# first check for internet connection
	iswifi = check_internet()
	if iswifi:
		baseURL = 'http://mesonet.org/index.php/dataMdfMts/dataController/getFile/'
		URL = baseURL + '%4.4d%2.2d%2.2d%s/mts/TEXT/' % (procYear, procMonth, 
			procDay, procStation.lower())
		fd = urllib2.urlopen(URL)
		data_long = fd.read()
		data = data_long.split('\n')
		time_, RH_, T2m_, T9m_, speed_, direction_, p_ = ([] for i in range(7))

		for i in np.arange(3, len(data)-1):
			time_.append(float(data[i].split()[2]))
			RH_.append(float(data[i].split()[3]))
			T2m_.append(float(data[i].split()[4]))
			T9m_.append(float(data[i].split()[14]))
			speed_.append(float(data[i].split()[5]))
			direction_.append(float(data[i].split()[7]))
			p_.append(float(data[i].split()[12]))

		speed_kts = [i * 1.94 for i in speed_]
		u,v = mcalc.get_wind_components(speed_kts*units.kts, direction_ * units.deg)
		u = u.to(units.kts) / units.kts
		v = v.to(units.kts) / units.kts

		return np.array([time_, RH_, T2m_, T9m_, u, v, p_])

	else:
		return np.array([])
Beispiel #5
0
def test_storm_relative_helicity():
    """Test function for SRH calculations on an eigth-circle hodograph."""
    # Create larger arrays for everything except pressure to make a smoother graph
    hgt_int = np.arange(0, 2050, 50)
    hgt_int = hgt_int * units('meter')
    dir_int = np.arange(180, 272.25, 2.25)
    spd_int = np.zeros((hgt_int.shape[0]))
    spd_int[:] = 2.
    u_int, v_int = get_wind_components(spd_int * units('m/s'),
                                       dir_int * units.degree)

    # Put in the correct value of SRH for a eighth-circle, 2 m/s hodograph
    # (SRH = 2 * area under hodo, in this case...)
    srh_true_p = (.25 * np.pi * (2**2)) * units('m^2/s^2')

    # Since there's only positive SRH in this case, total SRH will be equal to positive SRH and
    # negative SRH will be zero.
    srh_true_t = srh_true_p
    srh_true_n = 0 * units('m^2/s^2')
    p_srh, n_srh, T_srh = storm_relative_helicity(u_int,
                                                  v_int,
                                                  hgt_int,
                                                  1000 * units('meter'),
                                                  bottom=0 * units('meter'),
                                                  storm_u=0 * units.knot,
                                                  storm_v=0 * units.knot)
    assert_almost_equal(p_srh, srh_true_p, 2)
    assert_almost_equal(n_srh, srh_true_n, 2)
    assert_almost_equal(T_srh, srh_true_t, 2)
Beispiel #6
0
    def clean_up(self,
                 drop_time=True,
                 mask_invalid_wind=True,
                 mask_relative_wind=True,
                 convert_to_uv=True,
                 convert_to_mps=True):
        """
        Clean up the dataset and add essential attributes.

        Arguments
        ---------
        drop_time: bool
            Remove additional time variable (and leave only the index)
        mask_invalid_wind: bool
            Mask out wind speed and wind angle values if $INMWV Status is not "A"
        mask_relative_wind: bool
            Mask out wind speed and wind angle values if $INMWV Reference is not "T"
        convert_to_uv: bool
            Convert wind speed and wind angle to u- and v-components
        convert_to_mps: bool
            Convert units of wind speed and water speed from knots to m/s
        """
        self.ds.longitude.attrs['units'] = 'degrees_east'
        self.ds.latitude.attrs['units'] = 'degrees_north'

        if drop_time:
            self.ds = self.ds.drop(labels=['time'])
            self.ds.rename(dict(index='time'), inplace=True)
        if mask_invalid_wind:
            self.ds.wind_angle.values[self.ds.status != 'A'] = np.nan
            self.ds.wind_speed.values[self.ds.status != 'A'] = np.nan
            self.ds = self.ds.drop(labels=['status'])
        if mask_relative_wind:
            self.ds.wind_angle.values[self.ds.reference != 'T'] = np.nan
            self.ds.wind_speed.values[self.ds.reference != 'T'] = np.nan
            self.ds = self.ds.drop(labels=['reference'])
        if convert_to_mps:
            kt2mps = metunits.units('knots').to('m/s')
            self.ds['wind_speed'] *= kt2mps
            self.ds['water_speed_knots'] *= kt2mps
            self.ds.rename(dict(water_speed_knots='water_speed'), inplace=True)
        else:
            kt2mps = metunits.units('knots')

        if convert_to_uv:
            u, v = mcalc.get_wind_components(
                self.ds.wind_speed.values * kt2mps,
                self.ds.wind_angle.values * metunits.units('degrees'))
            self.ds = self.ds.drop(labels=['wind_speed', 'wind_angle'])
            self.ds = self.ds.assign(
                u=xr.Variable(dims='time',
                              data=u,
                              attrs=dict(units='m s**-1',
                                         long_name='U component of wind',
                                         short_name='eastward_wind')),
                v=xr.Variable(dims='time',
                              data=v,
                              attrs=dict(units='m s**-1',
                                         long_name='V component of wind',
                                         short_name='northward_wind')))
Beispiel #7
0
def get_upper_air_data(date, station):
    """Get upper air observations from the test data cache.

    Parameters
     ----------
    time : datetime
          The date and time of the desired observation.
    station : str
         The three letter ICAO identifier of the station for which data should be
         downloaded.
    Returns
    -------
        dict : upper air data

    """
    soudning_key = '{0:%Y-%m-%dT%HZ}_{1:}'.format(date, station)
    sounding_files = {'2016-05-22T00Z_DDC': 'may22_sounding.txt',
                      '2013-01-20T12Z_OUN': 'jan20_sounding.txt',
                      '1999-05-04T00Z_OUN': 'may4_sounding.txt',
                      '2002-11-11T00Z_BNA': 'nov11_sounding.txt',
                      '2010-12-09T12Z_BOI': 'dec9_sounding.txt'}

    fname = sounding_files[soudning_key]
    fobj = get_test_data(fname)

    def to_float(s):
        # Remove all whitespace and replace empty values with NaN
        if not s.strip():
            s = 'nan'
        return float(s)

    # Skip dashes, column names, units, and more dashes
    for _ in range(4):
        fobj.readline()

    # Initiate lists for variables
    arr_data = []

    # Read all lines of data and append to lists only if there is some data
    for row in fobj:
        level = to_float(row[0:7])
        values = (to_float(row[7:14]), to_float(row[14:21]), to_float(row[21:28]),
                  to_float(row[42:49]), to_float(row[49:56]))

        if any(np.invert(np.isnan(values[1:]))):
            arr_data.append((level,) + values)

    p, z, t, td, direc, spd = np.array(arr_data).T

    p = p * units.hPa
    z = z * units.meters
    t = t * units.degC
    td = td * units.degC
    direc = direc * units.degrees
    spd = spd * units.knots

    u, v = get_wind_components(spd, direc)

    return {'pressure': p, 'height': z, 'temperature': t,
            'dewpoint': td, 'direction': direc, 'speed': spd, 'u_wind': u, 'v_wind': v}
Beispiel #8
0
def get_obs(ts, mybb):
    # copied from the browser url box
    metar_cat_url = 'http://thredds.ucar.edu/thredds/catalog/nws/metar/ncdecoded/catalog.xml?dataset=nws/metar/ncdecoded/Metar_Station_Data_fc.cdmr'
    # parse the xml
    metar_cat = TDSCatalog(metar_cat_url)
    # what datasets are here? only one "dataset" in this catalog
    dataset = list(metar_cat.datasets.values())[0]
    ncss_url = dataset.access_urls["NetcdfSubset"]
    ncss = NCSS(ncss_url)

    query = ncss.query().accept('csv').time(ts - datetime.timedelta(minutes=1))
    query.lonlat_box(**mybb)
    query.variables('air_temperature', 'dew_point_temperature', 'inches_ALTIM',
                    'wind_speed', 'wind_from_direction', 'cloud_area_fraction', 'weather')

    try:
        data = ncss.get_data(query)
        lats = data['latitude'][:]
        lons = data['longitude'][:]
        tair = data['air_temperature'][:]
        dewp = data['dew_point_temperature'][:]
        slp = (data['inches_ALTIM'][:] * units('inHg')).to('mbar')

        # Convert wind to components
        u, v = mpcalc.get_wind_components(data['wind_speed'] * units.knot,
                                          data['wind_from_direction'] * units.deg)

        # Need to handle missing (NaN) and convert to proper code
        cloud_cover = 8 * data['cloud_area_fraction']
        cloud_cover[np.isnan(cloud_cover)] = 9
        cloud_cover = cloud_cover.astype(np.int)

        # For some reason these come back as bytes instead of strings
        stid = [s.decode() for s in data['station']]

        # Convert the text weather observations to WMO codes we can map to symbols
        if data['weather'].dtype != bool:
            wx_text = [s.decode('ascii') for s in data['weather']]
            wx_codes = np.array(list(to_code(wx_text)))
        else:
            wx_codes = np.array([0] * len(data['weather']))

        sfc_data = {'latitude': lats, 'longitude': lons,
                    'air_temperature': tair, 'dew_point_temperature': dewp, 'eastward_wind': u,
                    'northward_wind': v, 'cloud_coverage': cloud_cover,
                    'air_pressure_at_sea_level': slp, 'present_weather': wx_codes}

        have_obs = True
    except:
        have_obs = False
        sfc_data = {}

    return sfc_data, have_obs
Beispiel #9
0
def test_speed_dir_roundtrip():
    """Test round-tripping between speed/direction and components."""
    # Test each quadrant of the whole circle
    wspd = np.array([15., 5., 2., 10.]) * units.meters / units.seconds
    wdir = np.array([160., 30., 225., 350.]) * units.degrees

    u, v = get_wind_components(wspd, wdir)

    wdir_out = get_wind_dir(u, v)
    wspd_out = get_wind_speed(u, v)

    assert_array_almost_equal(wspd, wspd_out, 4)
    assert_array_almost_equal(wdir, wdir_out, 4)
Beispiel #10
0
def test_wind_comps_basic():
    """Test the basic wind component calculation."""
    speed = np.array([4, 4, 4, 4, 25, 25, 25, 25, 10.]) * units.mph
    dirs = np.array([0, 45, 90, 135, 180, 225, 270, 315, 360]) * units.deg
    s2 = np.sqrt(2.)

    u, v = get_wind_components(speed, dirs)

    true_u = np.array([0, -4 / s2, -4, -4 / s2, 0, 25 / s2, 25, 25 / s2, 0
                       ]) * units.mph
    true_v = np.array([-4, -4 / s2, 0, 4 / s2, 25, 25 / s2, 0, -25 / s2, -10
                       ]) * units.mph

    assert_array_almost_equal(true_u, u, 4)
    assert_array_almost_equal(true_v, v, 4)
Beispiel #11
0
def build_pd(stn_id):
    key = 'b1c91e501782441d97ac056e2501b5b0'
    m = Meso(token=key)
    time = m.timeseries(stid=stn_id, start='199801010000', end='201801010000')
    ob = time['STATION'][0]
    temp = np.expand_dims(np.array(ob['OBSERVATIONS']['air_temp_set_1'],
                                   dtype=np.float),
                          axis=1)
    wind_dir = np.expand_dims(np.array(
        ob['OBSERVATIONS']['wind_direction_set_1'], dtype=np.float),
                              axis=1) * units.degrees
    wind_spd = np.expand_dims(np.array(ob['OBSERVATIONS']['wind_speed_set_1'],
                                       dtype=np.float),
                              axis=1) * 1.9438445
    wind_max = np.expand_dims(np.array(
        ob['OBSERVATIONS']['peak_wind_speed_set_1'], dtype=np.float),
                              axis=1) * 1.9438445
    u, v = mpcalc.get_wind_components(wind_spd, wind_dir)
    rel_hum = np.expand_dims(np.array(
        ob['OBSERVATIONS']['relative_humidity_set_1'], dtype=np.float),
                             axis=1)

    dates = ob['OBSERVATIONS']['date_time']
    years = float(dates[0][0:4])
    months = float(dates[0][5:7])
    hours = float(dates[0][8:10])
    days = float(dates[0][11:13])

    for i in range(len(dates) - 1):
        years = np.vstack((years, float(dates[i + 1][0:4])))
        months = np.vstack((months, float(dates[i + 1][5:7])))
        days = np.vstack((days, float(dates[i + 1][8:10])))
        hours = np.vstack((hours, float(dates[i + 1][11:13])))

    minutes = np.expand_dims(np.ones(len(hours)) * 55.0, axis=1)
    cols = [
        'Year', 'Month', 'Day', 'Hour', 'Minutes', 'Temp', 'RH', 'Dir', 'Spd',
        'Max', 'U', 'V'
    ]
    data = np.hstack((years, months, days, hours, minutes, temp, rel_hum,
                      wind_dir, wind_spd, wind_max, u, v))
    data = pd.DataFrame(data=data, columns=cols)
    pickle.dump(data, open('../Data/pickles/' + stn_id + '_20yr_RAWS.p', 'wb'))
    return data
def plot_skewt(df):
    # We will pull the data out of the example dataset into individual variables
    # and assign units.
    p = df['pressure'].values * units.hPa
    T = df['temperature'].values * units.degC
    Td = df['dewpoint'].values * units.degC
    wind_speed = df['speed'].values * units.knots
    wind_dir = df['direction'].values * units.degrees
    u, v = mpcalc.get_wind_components(wind_speed, wind_dir)

    # Create a new figure. The dimensions here give a good aspect ratio.
    fig = plt.figure(figsize=(9, 9))
    add_metpy_logo(fig, 115, 100)
    skew = SkewT(fig, rotation=45)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, 'r')
    skew.plot(p, Td, 'g')
    skew.plot_barbs(p, u, v)
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    # Calculate LCL height and plot as black dot
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Calculate full parcel profile and add to plot as black line
    prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
    skew.plot(p, prof, 'k', linewidth=2)

    # An example of a slanted line at constant T -- in this case the 0
    # isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    return skew
Beispiel #13
0
def test_helicity():
    """Test function for SRH calculations on an eigth-circle hodograph."""
    pres_test = np.asarray([
        1013.25, 954.57955706, 898.690770743, 845.481604002, 794.85264282
    ]) * units('hPa')
    hgt_test = hgt_test = np.asarray([0, 500, 1000, 1500, 2000])

    # Create larger arrays for everything except pressure to make a smoother graph
    hgt_int = np.arange(0, 2050, 50)
    hgt_int = hgt_int * units('meter')
    dir_int = np.arange(180, 272.25, 2.25)
    spd_int = np.zeros((hgt_int.shape[0]))
    spd_int[:] = 2.
    u_int, v_int = get_wind_components(spd_int * units('m/s'),
                                       dir_int * units.degree)

    # Interpolate pressure to that graph
    pres_int = np.interp(hgt_int, hgt_test, np.log(pres_test.magnitude))
    pres_int = np.exp(pres_int) * units('hPa')

    # Put in the correct value of SRH for a eighth-circle, 2 m/s hodograph
    # (SRH = 2 * area under hodo, in this case...)
    srh_true_p = (.25 * np.pi * (2**2)) * units('m^2/s^2')

    # Since there's only positive SRH in this case, total SRH will be equal to positive SRH and
    # negative SRH will be zero.
    srh_true_t = srh_true_p
    srh_true_n = 0 * units('m^2/s^2')
    p_srh, n_srh, T_srh = storm_relative_helicity(u_int,
                                                  v_int,
                                                  pres_int,
                                                  hgt_int,
                                                  1000 * units('meter'),
                                                  bottom=0 * units('meter'),
                                                  storm_u=0 * units.knot,
                                                  storm_v=0 * units.knot)
    assert_almost_equal(p_srh, srh_true_p, 2)
    assert_almost_equal(n_srh, srh_true_n, 2)
    assert_almost_equal(T_srh, srh_true_t, 2)
# Remove bad data from wind information
wind_speed = np.array([w[0] for w in wind])
wind_dir = np.array([w[1] for w in wind])

good_indices = np.where((~np.isnan(wind_dir)) & (~np.isnan(wind_speed)))

x = x[good_indices]
y = y[good_indices]
wind_speed = wind_speed[good_indices]
wind_dir = wind_dir[good_indices]

###########################################
# Calculate u and v components of wind and then interpolate both.
#
# Both will have the same underlying grid so throw away grid returned from v interpolation.
u, v = get_wind_components((wind_speed * units('m/s')).to('knots'),
                           wind_dir * units.degree)

windgridx, windgridy, uwind = interpolate(x, y, np.array(u), interp_type='cressman',
                                          search_radius=400000, hres=100000)

_, _, vwind = interpolate(x, y, np.array(v), interp_type='cressman', search_radius=400000,
                          hres=100000)

###########################################
# Get temperature information
levels = list(range(-20, 20, 1))
cmap = plt.get_cmap('viridis')
norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)

xt, yt, t = station_test_data('air_temperature', from_proj, to_proj)
xt, yt, t = remove_nan_observations(xt, yt, t)
                0),
            np.nanmean(
                np.cos(Direction_deg[indCopter][indTimeAvg] * np.pi / 180.),
                0)) * 180. / np.pi

########################################
## Convert wind to kts, fix direction ##
########################################

#wind_kts = np.array([w * 1.94 for w in wind])
wind_kts = wind * 1.94

iNeg = np.squeeze(np.where(direction < 0.))
direction[iNeg] = direction[iNeg] + 360.

u, v = mcalc.get_wind_components(wind_kts * units.kts, direction * units.deg)
u = u.to(units.kts)
v = v.to(units.kts)

##################################
## Find average between sensors ##
##################################

TArr = np.array([t1, t2, t3, t4])
RHArr = np.array([rh1, rh2, rh3, rh4])

Tmean = np.nanmean(TArr, 0)
RHmean = np.nanmean(RHArr, 0)
if np.isnan(RHmean).all():
    isRH = 0
else:
Beispiel #16
0
def plotUAVskewT(filenamecsv):
	'''
	Input filepath of post-processed uav data

	Outputs Skew-T log-p plot of UAV data, includes hodograph and some
	convective parameters
	'''
	copdata = csvread_copter(filenamecsv)
	lat = copdata[0]
	lon = copdata[1]
	alt = copdata[2]
	pressure = copdata[3]
	temperature = copdata[4]
	dewpoint = copdata[5]
	speed = copdata[9]
	speed_kts = speed * 1.94
	direction = copdata[10]
	site = findSite(lat[0], lon[0])
	sitename, sitelong = site.split('/')
	fname = filenamecsv.split('\\')[-1]
	timeTakeoff = datetime.strptime(fname[:15], '%Y%m%d_%H%M%S')
	copterNum = fname[-10]

	u,v = mcalc.get_wind_components(speed_kts*units.kts, direction * units.deg)
	u = u.to(units.kts)
	v = v.to(units.kts)
	# Wind shear
	bulkshear = speed_kts[-3] - speed_kts[0]
	print '0-%d m Bulk Shear: %.0f kts' % (alt[-3], bulkshear)
	if np.isnan(dewpoint).all():
		moist = 0
	else: 
		moist = 1


	print 'Plotting...'
	fignum = plt.figure(figsize=(12,9))
	gs = gridspec.GridSpec(4, 4)
	skew = SkewT(fignum, rotation=20, subplot=gs[:, :2])

	skew.plot(pressure, temperature, 'r', linewidth = 2)
	skew.plot(pressure, dewpoint, 'g', linewidth = 2)
	skew.plot_barbs(pressure[0::4], u[0::4], v[0::4], x_clip_radius = 0.12, \
	    y_clip_radius = 0.12)

	# Plot convective parameters
	if moist:
		plcl, Tlcl, isbelowlcl, profile = parcelUAV(temperature,
			dewpoint, pressure)
		SBCAPE = uavCAPE(temperature * units.degC, profile,
			pressure * units.hPa)
		skew.plot(plcl, Tlcl, 'ko', markerfacecolor='black')
		skew.plot(pressure, profile, 'k', linewidth=2)
	else:
		isbelowlcl = 0

	# set up plot limits and labels - use LCL as max if higher than profile
	# if moist:
	#     xmin = math.floor(np.nanmin(dewpoint)) + 2
	# else:
	#     xmin = math.floor(np.nanmin(temperature))
	# xmax = math.floor(np.nanmax(temperature)) + 20
	xmin = 0.
	xmax = 50.
	if isbelowlcl:
	    ymin = round((plcl / units.mbar), -1) - 10
	else:
	    ymin = round(np.nanmin(pressure),-1) - 10
	    
	ymax = round(np.nanmax(pressure),-1) + 10

	skew.ax.set_ylim(ymax, ymin)
	skew.ax.set_xlim(xmin, xmax)
	skew.ax.set_yticks(np.arange(ymin, ymax+10, 10))

	skew.ax.set_xlabel('Temperature ($^\circ$C)')
	skew.ax.set_ylabel('Pressure (hPa)')
	titleName = 'Coptersonde-%s %s UTC - %s' % (copterNum, 
	    timeTakeoff.strftime('%d-%b-%Y %H:%M:%S'), sitename)
	skew.ax.set_title(titleName)

	skew.plot_dry_adiabats(linewidth=0.75)
	skew.plot_moist_adiabats(linewidth=0.75)
	skew.plot_mixing_lines(linewidth=0.75)

	# Hodograph
	ax_hod = fignum.add_subplot(gs[:2,2:])
	#gs.tight_layout(fig5)
	if np.nanmax(speed_kts) > 18:
	    comprange = 35
	else:
	    comprange = 20

	h = Hodograph(ax_hod, component_range=comprange)
	h.add_grid(increment=5)
	h.plot_colormapped(u, v, pressure, cmap=cmocean.cm.deep_r)
	ax_hod.set_title('Hodograph (kts)')
	ax_hod.yaxis.set_ticklabels([])
	#ax_hod.set_xlabel('Wind Speed (kts)')

	# Map - Oklahoma
	llcrnrlat = 33.6
	urcrnrlat = 37.2
	llcrnrlon = -103.2
	urcrnrlon = -94.2
	ax_map = fignum.add_subplot(gs[2, 2:])

	m = Basemap(projection='merc', llcrnrlat=llcrnrlat, urcrnrlat=urcrnrlat, 
	    llcrnrlon=llcrnrlon,urcrnrlon=urcrnrlon, lat_ts=20, resolution='l',
	    ax=ax_map)

	print 'Basemap...'
	m.drawcounties()
	m.drawstates()
	x,y = m(lon[0], lat[0])
	plt.plot(x,y,'b.')
	plt.text(x+40000, y-5000, sitelong, 
		bbox=dict(facecolor='yellow', alpha=0.5))

	if moist:
	    # Convective parameter values
	    ax_data = fignum.add_subplot(gs[3, 2])
	    plt.axis('off')
	    datastr = 'LCL = %.0f hPa\nSBCAPE = %.0f J kg$^{-1}$\n0-%.0f m bulk shear\n\
	    = %.0f kts' % \
	        (plcl.magnitude, SBCAPE.magnitude, alt[-3], bulkshear)
	    boxprops = dict(boxstyle='round', facecolor='none')
	    ax_data.text(0.05, 0.95, datastr, transform=ax_data.transAxes, 
	    	fontsize=14, verticalalignment='top', bbox=boxprops)
	    # Logos
	    ax_png = fignum.add_subplot(gs[3, 3])
	    img = mpimg.imread(logoName)
	    plt.axis('off')
	    plt.imshow(img)
	else:
	    # Logos
	    ax_png = fignum.add_subplot(gs[3, 2:])
	    img = mpimg.imread(logoName)
	    plt.axis('off')
	    plt.imshow(img)

	plt.show(block=False)
	return
Beispiel #17
0
def do(ts):
    """Process this date timestamp"""
    asos = get_dbconn('asos', user='******')
    iemaccess = get_dbconn('iem')
    icursor = iemaccess.cursor()
    df = read_sql("""
    select station, network, iemid, drct, sknt,
    valid at time zone tzname as localvalid,
    tmpf, dwpf from
    alldata d JOIN stations t on (t.id = d.station)
    where (network ~* 'ASOS' or network = 'AWOS')
    and valid between %s and %s and t.tzname is not null
    and date(valid at time zone tzname) = %s
    ORDER by valid ASC
    """, asos, params=(ts - datetime.timedelta(days=2),
                       ts + datetime.timedelta(days=2),
                       ts.strftime("%Y-%m-%d")), index_col=None)
    # derive some parameters
    df['relh'] = mcalc.relative_humidity_from_dewpoint(
        df['tmpf'].values * munits.degF,
        df['dwpf'].values * munits.degF).to(munits.percent)
    df['feel'] = mcalc.apparent_temperature(
        df['tmpf'].values * munits.degF,
        df['relh'].values * munits.percent,
        df['sknt'].values * munits.knots
    )
    df['u'], df['v'] = mcalc.get_wind_components(
        df['sknt'].values * munits.knots,
        df['drct'].values * munits.deg
    )
    df['localvalid_lag'] = df.groupby('iemid')['localvalid'].shift(1)
    df['timedelta'] = df['localvalid'] - df['localvalid_lag']
    ndf = df[pd.isna(df['timedelta'])]
    df.loc[ndf.index.values, 'timedelta'] = pd.to_timedelta(
            ndf['localvalid'].dt.hour * 3600. +
            ndf['localvalid'].dt.minute * 60., unit='s'
    )
    df['timedelta'] = df['timedelta'] / np.timedelta64(1, 's')

    table = "summary_%s" % (ts.year,)
    for iemid, gdf in df.groupby('iemid'):
        if len(gdf.index) < 6:
            # print(" Quorum not meet for %s" % (gdf.iloc[0]['station'], ))
            continue
        ldf = gdf.copy()
        ldf.interpolate(inplace=True)
        totsecs = ldf['timedelta'].sum()
        avg_rh = clean((ldf['relh'] * ldf['timedelta']).sum() / totsecs, 1,
                       100)
        min_rh = clean(ldf['relh'].min(), 1, 100)
        max_rh = clean(ldf['relh'].max(), 1, 100)

        uavg = (ldf['u'] * ldf['timedelta']).sum() / totsecs
        vavg = (ldf['u'] * ldf['timedelta']).sum() / totsecs
        drct = clean(
            mcalc.get_wind_dir(uavg * munits.knots, vavg * munits.knots),
            0, 360)
        avg_sknt = clean(
            (ldf['sknt'] * ldf['timedelta']).sum() / totsecs, 0, 150  # arb
        )
        max_feel = clean(ldf['feel'].max(), -150, 200)
        avg_feel = clean(
            (ldf['feel'] * ldf['timedelta']).sum() / totsecs, -150, 200
        )
        min_feel = clean(ldf['feel'].min(), -150, 200)

        def do_update():
            """Inline updating"""
            icursor.execute("""
            UPDATE """ + table + """
            SET avg_rh = %s, min_rh = %s, max_rh = %s,
            avg_sknt = %s, vector_avg_drct = %s,
            min_feel = %s, avg_feel = %s, max_feel = %s
            WHERE
            iemid = %s and day = %s
            """, (avg_rh, min_rh, max_rh, avg_sknt, drct,
                  min_feel, avg_feel, max_feel,
                  iemid, ts))
        do_update()
        if icursor.rowcount == 0:
            print(('compute_daily Adding %s for %s %s %s'
                   ) % (table, gdf.iloc[0]['station'], gdf.iloc[0]['network'],
                        ts))
            icursor.execute("""
                INSERT into """ + table + """
                (iemid, day) values (%s, %s)
            """, (iemid, ts))
            do_update()

    icursor.close()
    iemaccess.commit()
    iemaccess.close()
Beispiel #18
0
def test_get_wind_components():
    """Test that get_wind_components wrapper works (deprecated in 0.9)."""
    u, v = get_wind_components(8 * units('m/s'), 150 * units.deg)
    assert_almost_equal(u, -4 * units('m/s'), 3)
    assert_almost_equal(v, 6.9282 * units('m/s'), 3)
Beispiel #19
0
# Remove bad data from wind information
wind_speed = np.array([w[0] for w in wind])
wind_dir = np.array([w[1] for w in wind])

good_indices = np.where((~np.isnan(wind_dir)) & (~np.isnan(wind_speed)))

x = x[good_indices]
y = y[good_indices]
wind_speed = wind_speed[good_indices]
wind_dir = wind_dir[good_indices]

###########################################
# Calculate u and v components of wind and then interpolate both.
#
# Both will have the same underlying grid so throw away grid returned from v interpolation.
u, v = get_wind_components((wind_speed * units('m/s')).to('knots'),
                           wind_dir * units.degree)

windgridx, windgridy, uwind = interpolate(x,
                                          y,
                                          np.array(u),
                                          interp_type='cressman',
                                          search_radius=400000,
                                          hres=100000)

_, _, vwind = interpolate(x,
                          y,
                          np.array(v),
                          interp_type='cressman',
                          search_radius=400000,
                          hres=100000)
Beispiel #20
0
h_new_labels = h_new_labels[0:index + 1]
p_interped_func = interpolate.interp1d(h, p)
p_interped = p_interped_func(h_new[0:index + 1])

# Add units to the data arrays
p = p * units.mbar
p_std = p_std * units.mbar
T = T * units.degC
Td = Td * units.degC
spd = spd * units.knot
spd_std = spd_std * units.knot
direc = direc * units.deg
direc_std = direc_std * units.deg

# Convert wind speed and direction to components
u, v = get_wind_components(spd, direc)
u_std, v_std = get_wind_components(spd_std, direc_std)

#PARCEL CALCULATIONS with sharppy
sfcpcl = params.parcelx(prof, flag=1)  # Surface Parcel
fcstpcl = params.parcelx(prof, flag=2)  # Forecast Parcel
mupcl = params.parcelx(prof, flag=3)  # Most-Unstable Parcel
mlpcl = params.parcelx(prof, flag=4)  # 100 mb Mean Layer Parcel

sfc = prof.pres[prof.sfc]
p3km = interp.pres(prof, interp.to_msl(prof, 3000.))
p6km = interp.pres(prof, interp.to_msl(prof, 6000.))
p1km = interp.pres(prof, interp.to_msl(prof, 1000.))
mean_3km = winds.mean_wind(prof, pbot=sfc, ptop=p3km)
sfc_6km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p6km)
sfc_3km_shear = winds.wind_shear(prof, pbot=sfc, ptop=p3km)
Beispiel #21
0
def test_warning_dir():
    """Test that warning is raised wind direction > 2Pi."""
    with pytest.warns(UserWarning):
        get_wind_components(3. * units('m/s'), 270)
Beispiel #22
0
# coding: utf-8
import matplotlib.pyplot as plt
import numpy as np

from metpy.calc import get_wind_components
from metpy.plots import SkewT

# Parse the data
p, T, Td, direc, spd = np.loadtxt('../testdata/sounding_data.txt',
        usecols=(0, 2, 3, 6, 7), unpack=True)
u, v = get_wind_components(spd, direc)

# Create a new figure. The dimensions here give a good aspect ratio
fig = plt.figure(figsize=(9, 9))
skew = SkewT(fig)

# Plot the data using normal plotting functions, in this case using
# log scaling in Y, as dictated by the typical meteorological plot
skew.plot(p, T, 'r')
skew.plot(p, Td, 'g')
skew.plot_barbs(p, u, v)

# Add the relevant special lines
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()
skew.ax.set_ylim(1000, 100)

# Show the plot
plt.show()
# Get wind information and mask where either speed or direction is unavailable
wind_speed = (data['wind_speed'].values * units('m/s')).to('knots')
wind_dir = data['wind_dir'].values * units.degree

good_indices = np.where((~np.isnan(wind_dir)) & (~np.isnan(wind_speed)))

x_masked = xp[good_indices]
y_masked = yp[good_indices]
wind_speed = wind_speed[good_indices]
wind_dir = wind_dir[good_indices]

###########################################
# Calculate u and v components of wind and then interpolate both.
#
# Both will have the same underlying grid so throw away grid returned from v interpolation.
u, v = get_wind_components(wind_speed, wind_dir)

windgridx, windgridy, uwind = interpolate(x_masked,
                                          y_masked,
                                          np.array(u),
                                          interp_type='cressman',
                                          search_radius=400000,
                                          hres=100000)

_, _, vwind = interpolate(x_masked,
                          y_masked,
                          np.array(v),
                          interp_type='cressman',
                          search_radius=400000,
                          hres=100000)
# Set up the map projection
proj = ccrs.LambertConformal(central_longitude=13, central_latitude=47,
                             standard_parallels=[35])
# Use the cartopy map projection to transform station locations to the map and
# then refine the number of stations plotted by setting a 300km radius
point_locs = proj.transform_points(ccrs.PlateCarree(), df['longitude'].values, df['latitude'].values)
df = df[reduce_point_density(point_locs, 1000.)]

# Map weather strings to WMO codes, which we can use to convert to symbols
# Only use the first symbol if there are multiple
df['weather'] = df['weather'].replace('-SG','SG')
df['weather'] = df['weather'].replace('FZBR','FZFG')
wx = [wx_code_map[s.split()[0] if ' ' in s else s] for s in df['weather'].fillna('')]
# Get the wind components, converting from m/s to knots as will be appropriate
# for the station plot.
u, v = get_wind_components(((df['wind_speed'].values)*units('m/s')).to('knots'),
                           (df['wind_from_direction'].values) * units.degree)
cloud_frac = df['cloud_area_fraction']

# Change the DPI of the resulting figure. Higher DPI drastically improves the
# look of the text rendering.
# plt.rcParams['savefig.dpi'] = 100


# ============================================================================
# Create the figure and an axes set to the projection.
# fig = plt.figure(figsize=(20, 8))
# ax = fig.add_subplot(1, 1, 1, projection=proj)
# # Set up a cartopy feature for state borders.
state_boundaries = feat.NaturalEarthFeature(category='cultural',
                                             name='admin_0_countries',
                                            scale='10m', facecolor='none')
Beispiel #25
0
# then refine the number of stations plotted by setting a 300km radius
point_locs = proj.transform_points(ccrs.PlateCarree(), data['lon'].values,
                                   data['lat'].values)
data = data[reduce_point_density(point_locs, 300000.)]

###########################################
# Now that we have the data we want, we need to perform some conversions:
#
# - Get wind components from speed and direction
# - Convert cloud fraction values to integer codes [0 - 8]
# - Map METAR weather codes to WMO codes for weather symbols

# Get the wind components, converting from m/s to knots as will be appropriate
# for the station plot.
u, v = get_wind_components(
    (data['wind_speed'].values * units('m/s')).to('knots'),
    data['wind_dir'].values * units.degree)

# Convert the fraction value into a code of 0-8 and compensate for NaN values,
# which can be used to pull out the appropriate symbol
cloud_frac = (8 * data['cloud_fraction'])
cloud_frac[np.isnan(cloud_frac)] = 10
cloud_frac = cloud_frac.astype(int)

# Map weather strings to WMO codes, which we can use to convert to symbols
# Only use the first symbol if there are multiple
wx_codes = {
    '': 0,
    'HZ': 5,
    'BR': 10,
    '-DZ': 51,
text_time = ax.text(0.01,
                    0.01,
                    timestamp.strftime('%d %B %Y %H%MZ'),
                    horizontalalignment='left',
                    transform=ax.transAxes,
                    color='white',
                    fontsize=100,
                    weight='bold')

outline_effect = [patheffects.withStroke(linewidth=15, foreground='black')]
text_time.set_path_effects(outline_effect)

ax.set_extent([-124.5, -105, 38.5, 50])

# Transform plane heading to a map direction and plot a rotated marker
u, v = mpcalc.get_wind_components(1 * units('m/s'),
                                  data['heading'] * units('degrees'))
u, v = proj.transform_vectors(ccrs.PlateCarree(),
                              np.array([data['longitude']]),
                              np.array([data['latitude']]), np.array([u.m]),
                              np.array([v.m]))
map_direction = -mpcalc.get_wind_dir(u, v).to('degrees')
map_direction = map_direction[0].m

ax.scatter(data['longitude'],
           data['latitude'],
           transform=ccrs.PlateCarree(),
           marker=(3, 0, map_direction),
           color='red',
           s=4000)

ax.text(data['longitude'],
data['dew_point_temperature'] = data_arr['dewpoint'] * units.degC
data['air_pressure_at_sea_level'] = data_arr['slp'] * units('mbar')

###########################################
# Notice that the names (the keys) in the dictionary are the same as those that the
# layout is expecting.
#
# Now perform a few conversions:
#
# - Get wind components from speed and direction
# - Convert cloud fraction values to integer codes [0 - 8]
# - Map METAR weather codes to WMO codes for weather symbols

# Get the wind components, converting from m/s to knots as will be appropriate
# for the station plot
u, v = get_wind_components(data_arr['wind_speed'] * units('m/s'),
                           data_arr['wind_dir'] * units.degree)
data['eastward_wind'], data['northward_wind'] = u, v

# Convert the fraction value into a code of 0-8, which can be used to pull out
# the appropriate symbol
data['cloud_coverage'] = (8 * data_arr['cloud_fraction']).astype(int)

# Map weather strings to WMO codes, which we can use to convert to symbols
# Only use the first symbol if there are multiple
wx_text = [s.decode('ascii') for s in data_arr['weather']]
wx_codes = {'': 0, 'HZ': 5, 'BR': 10, '-DZ': 51, 'DZ': 53, '+DZ': 55,
            '-RA': 61, 'RA': 63, '+RA': 65, '-SN': 71, 'SN': 73, '+SN': 75}
data['present_weather'] = [wx_codes[s.split()[0] if ' ' in s else s] for s in wx_text]

###########################################
# All the data wrangling is finished, just need to set up plotting and go:
Beispiel #28
0
def test_wind_comps_scalar():
    """Test wind components calculation with scalars."""
    u, v = get_wind_components(8 * units('m/s'), 150 * units.deg)
    assert_almost_equal(u, -4 * units('m/s'), 3)
    assert_almost_equal(v, 6.9282 * units('m/s'), 3)
Beispiel #29
0
def plot_upper_air(station='11035', date=False):
    '''
    -----------------------------
    Default use of plot_upper_air:

    This will plot a SkewT sounding for station '11035' (Wien Hohe Warte)
    plot_upper_air(station='11035', date=False)
    '''
    # sns.set(rc={'axes.facecolor':'#343837', 'figure.facecolor':'#343837',
    #  'grid.linestyle':'','axes.labelcolor':'#04d8b2','text.color':'#04d8b2',
    #  'xtick.color':'#04d8b2','ytick.color':'#04d8b2'})
    # Get time in UTC
    station = str(station)
    if date is False:
        now = datetime.utcnow()
        # If morning then 0z sounding, otherwise 12z
        if now.hour < 12:
            hour = 0
        else:
            hour = 12
        date = datetime(now.year, now.month, now.day, hour)
        datestr = date.strftime('%Hz %Y-%m-%d')
        print('{}'.format(date))
    else:
        year = int(input('Please specify the year: '))
        month = int(input('Please specify the month: '))
        day = int(input('Please specify the day: '))
        hour = int(input('Please specify the hour: '))
        if hour < 12:
            hour = 0
        else:
            hour = 12
        date = datetime(year, month, day, hour)
        datestr = date.strftime('%Hz %Y-%m-%d')
        print('You entered {}'.format(date))

    # This requests the data 11035 is
    df = WyomingUpperAir.request_data(date, station)

    # Create single variables wih the right units
    p = df['pressure'].values * units.hPa
    T = df['temperature'].values * units.degC
    Td = df['dewpoint'].values * units.degC
    wind_speed = df['speed'].values * units.knots
    wind_dir = df['direction'].values * units.degrees

    wind_speed_6k = df['speed'][df.height <= 6000].values * units.knots
    wind_dir_6k = df['direction'][df.height <= 6000].values * units.degrees

    u, v = mpcalc.get_wind_components(wind_speed, wind_dir)
    u6, v6 = mpcalc.get_wind_components(wind_speed_6k, wind_dir_6k)

    # Calculate the LCL
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    print(lcl_pressure, lcl_temperature)
    # Calculate the parcel profile.
    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
    cape, cin = mpcalc.cape_cin(p, T, Td, parcel_prof)

    #############################
    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(9, 9))
    gs = gridspec.GridSpec(3, 3)
    skew = SkewT(fig, rotation=45, subplot=gs[:, :2])

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, 'r')
    skew.plot(p, Td, 'g')
    skew.plot_barbs(p, u, v)
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-45, 40)

    # Plot LCL as black dot
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Plot the parcel profile as a black line
    skew.plot(p, parcel_prof, 'k', linewidth=2)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p, T, parcel_prof)
    skew.shade_cape(p, T, parcel_prof)

    # Plot a zero degree isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)
    skew.ax.set_title('Station: ' + str(station) + '\n' + datestr)  # set title
    skew.ax.set_xlabel('Temperature (C)')
    skew.ax.set_ylabel('Pressure (hPa)')

    # Add the relevant special lines
    skew.plot_dry_adiabats(linewidth=0.7)
    skew.plot_moist_adiabats(linewidth=0.7)
    skew.plot_mixing_lines(linewidth=0.7)

    # Create a hodograph
    # Create an inset axes object that is 40% width and height of the
    # figure and put it in the upper right hand corner.
    # ax_hod = inset_axes(skew.ax, '40%', '40%', loc=1)
    ax = fig.add_subplot(gs[0, -1])
    h = Hodograph(ax, component_range=60.)
    h.add_grid(increment=20)
    # Plot a line colored by windspeed
    h.plot_colormapped(u6, v6, wind_speed_6k)

    # add another subplot for the text of the indices
    # ax_t = fig.add_subplot(gs[1:,2])
    skew2 = SkewT(fig, rotation=0, subplot=gs[1:, 2])
    skew2.plot(p, T, 'r')
    skew2.plot(p, Td, 'g')
    # skew2.plot_barbs(p, u, v)
    skew2.ax.set_ylim(1000, 700)
    skew2.ax.set_xlim(-30, 10)

    # Show the plot
    plt.show()

    return cape
Beispiel #30
0
# print(avg_speed.to_base_units())  # put in the base units (m/s)
# print(avg_speed.to('mph'))        # put in mph

# # It also lets us avoid worrying about the exact units of arguments to
# # calculation functions:
# from metpy.calc import saturation_vapor_pressure
# e = saturation_vapor_pressure(Td)
# es = saturation_vapor_pressure(T)
# rh = e / es   # relative humidity
# print(e)   # in millibar
# print(es)  # in millibar
# print(rh)  # dimensionless

# Convert wind speed and direction to components
from metpy.calc import get_wind_components
u, v = get_wind_components(spd, direc)

################## PLOTTING ON A SKEW-T logP ######################
import matplotlib.pyplot as plt
from metpy.plots import SkewT

# create a new figure. The dimensions here gove a good aspect ratio
fig = plt.figure(figsize=(7, 9))
skew = SkewT(fig)              # passing the figure, use skewT

# Plot the data using normal plotting functions, in this case using
# log scaling in Y, as dictated by the typical meteorological plot
skew.plot(p, T, 'r')           # pressure and temperature in red
skew.plot(p, Td, 'g')
skew.plot_barbs(p, u, v)
skew.ax.set_ylim(1000, 100)    # Y limits from 1000 in the botton to 100 millibars to the top
Beispiel #31
0
def test_get_wind_components():
    """Test that get_wind_components wrapper works (deprecated in 0.9)."""
    with pytest.warns(MetpyDeprecationWarning):
        u, v = get_wind_components(8 * units('m/s'), 150 * units.deg)
    assert_almost_equal(u, -4 * units('m/s'), 3)
    assert_almost_equal(v, 6.9282 * units('m/s'), 3)
Beispiel #32
0
data['dew_point_temperature'] = data_arr['dew_point_temperature'] * units.degC
data['air_pressure_at_sea_level'] = data_arr['slp'] * units('mbar')

###########################################
# Notice that the names (the keys) in the dictionary are the same as those that the
# layout is expecting.
#
# Now perform a few conversions:
#
# - Get wind components from speed and direction
# - Convert cloud fraction values to integer codes [0 - 8]
# - Map METAR weather codes to WMO codes for weather symbols

# Get the wind components, converting from m/s to knots as will be appropriate
# for the station plot
u, v = get_wind_components(data_arr['wind_speed'] * units('m/s'),
                           data_arr['wind_dir'] * units.degree)
data['eastward_wind'], data['northward_wind'] = u, v

# Convert the fraction value into a code of 0-8, which can be used to pull out
# the appropriate symbol
data['cloud_coverage'] = (8 * data_arr['cloud_fraction']).astype(int)

# Map weather strings to WMO codes, which we can use to convert to symbols
# Only use the first symbol if there are multiple
wx_text = [s.decode('ascii') for s in data_arr['weather']]
wx_codes = {
    '': 0,
    'HZ': 5,
    'BR': 10,
    '-DZ': 51,
    'DZ': 53,
Beispiel #33
0
def test_wind_comps_scalar():
    """Test wind components calculation with scalars."""
    u, v = get_wind_components(8 * units('m/s'), 150 * units.deg)
    assert_almost_equal(u, -4 * units('m/s'), 3)
    assert_almost_equal(v, 6.9282 * units('m/s'), 3)
Beispiel #34
0
def test_get_wind_components():
    """Test that get_wind_components wrapper works (deprecated in 0.9)."""
    with pytest.warns(MetpyDeprecationWarning):
        u, v = get_wind_components(8 * units('m/s'), 150 * units.deg)
    assert_almost_equal(u, -4 * units('m/s'), 3)
    assert_almost_equal(v, 6.9282 * units('m/s'), 3)
Beispiel #35
0
import metpy.calc as mpcalc
from metpy.units import units

data = pd.read_csv(
    '~/Data/masdar_station_data/wyoming/metar+rs/201712/AbuDhabi_upperair_2017122112.csv'
)
data = data.apply(pd.to_numeric, errors='coerce')
#pd.set_option('display.float_format', '{:.2E}'.format)
#new_data=pd.concat([data['PRES'][1::][::-1],data['TEMP'][1::][::-1]+273.15,data['MIXR'][1::][::-1]/1000,data['MIXR'][1::][::-1]*0,(data['MIXR'][1::][::-1]*0).astype(int) ],axis=1 )
#new_data.to_csv('/home/vkvalappil/Data/modelWRF/LES/UCLALES-SALSA/bin/datafiles/dsrt.lay',sep=',',index=False,float_format='%.3E')

wind_speed = (data['SKNT'] * 0.514).values * units('m/s')
wind_dir = data['DRCT'].values * units.deg

#data['u_wind'], data['v_wind'] = mpcalc.get_wind_components(data['SKNT'][1::]*0.51,np.deg2rad(data['DRCT'][1::]))
data['u_wind'], data['v_wind'] = mpcalc.get_wind_components(
    wind_speed, wind_dir)

#u, v = mpcalc.get_wind_components(data['SKNT'][1::], data['DRCT'][1::])

new_data = pd.concat([
    data['HGHT'][1::], data['TEMP'][1::] + 273.15, data['MIXR'][1::],
    data['u_wind'][1::], data['v_wind'][1::]
],
                     axis=1)
new_data.to_csv(
    '/home/vkvalappil/Data/modelWRF/LES/UCLALES-SALSA/bin/sound_in_2017122112',
    sep=',',
    index=False)
#float_format='%.3E'
Beispiel #36
0
from metpy.units import units

###########################################
# Upper air data can be obtained using the siphon package, but for this example we will use
# some of MetPy's sample data.

col_names = [
    'pressure', 'height', 'temperature', 'dewpoint', 'direction', 'speed'
]

df = pd.read_fwf(get_test_data('may4_sounding.txt', as_file_obj=False),
                 skiprows=5,
                 usecols=[0, 1, 2, 3, 6, 7],
                 names=col_names)

df['u_wind'], df['v_wind'] = mpcalc.get_wind_components(
    df['speed'], np.deg2rad(df['direction']))

# Drop any rows with all NaN values for T, Td, winds
df = df.dropna(subset=('temperature', 'dewpoint', 'direction', 'speed',
                       'u_wind', 'v_wind'),
               how='all').reset_index(drop=True)

###########################################
# We will pull the data out of the example dataset into individual variables and
# assign units.

p = df['pressure'].values * units.hPa
T = df['temperature'].values * units.degC
Td = df['dewpoint'].values * units.degC
wind_speed = df['speed'].values * units.knots
wind_dir = df['direction'].values * units.degrees
Beispiel #37
0
data = np.concatenate([all_data[all_stids.index(site)].reshape(1,) for site in whitelist])

###########################################
# Now that we have the data we want, we need to perform some conversions:
#
# - Get a list of strings for the station IDs
# - Get wind components from speed and direction
# - Convert cloud fraction values to integer codes [0 - 8]
# - Map METAR weather codes to WMO codes for weather symbols

# Get all of the station IDs as a list of strings
stid = [s.decode('ascii') for s in data['stid']]

# Get the wind components, converting from m/s to knots as will be appropriate
# for the station plot
u, v = get_wind_components((data['wind_speed'] * units('m/s')).to('knots'),
                           data['wind_dir'] * units.degree)

# Convert the fraction value into a code of 0-8, which can be used to pull out
# the appropriate symbol
cloud_frac = (8 * data['cloud_fraction']).astype(int)

# Map weather strings to WMO codes, which we can use to convert to symbols
# Only use the first symbol if there are multiple
wx_text = [s.decode('ascii') for s in data['weather']]
wx_codes = {'': 0, 'HZ': 5, 'BR': 10, '-DZ': 51, 'DZ': 53, '+DZ': 55,
            '-RA': 61, 'RA': 63, '+RA': 65, '-SN': 71, 'SN': 73, '+SN': 75}
wx = [wx_codes[s.split()[0] if ' ' in s else s] for s in wx_text]

###########################################
# Now all the data wrangling is finished, just need to set up plotting and go
# Set up the map projection and set up a cartopy feature for state borders
Beispiel #38
0
def radar_plus_obs(station, my_datetime, radar_title=None, bb=None,
                   station_radius=75000., station_layout=simple_layout,
                  field='reflectivity', vmin=None, vmax=None,
                  sweep=0):
    if radar_title is None:
        radar_title = 'Area '

    radar = get_radar_from_aws(station, my_datetime)

    # Lets get some geographical context
    if bb is None:
        lats = radar.gate_latitude
        lons = radar.gate_longitude

        min_lon = lons['data'].min()
        min_lat = lats['data'].min()
        max_lat = lats['data'].max()
        max_lon = lons['data'].max()
        bb = {'north' : max_lat,
              'south' : min_lat,
              'east' : max_lon,
              'west' : min_lon}
    else:
        min_lon = bb['west']
        min_lat = bb['south']
        max_lon = bb['east']
        max_lat = bb['north']

    print('min_lat:', min_lat, ' min_lon:', min_lon,
          ' max_lat:', max_lat, ' max_lon:', max_lon)

    index_at_start = radar.sweep_start_ray_index['data'][sweep]
    time_at_start_of_radar = num2date(radar.time['data'][index_at_start],
                                      radar.time['units'])
    pacific = pytz.timezone('US/Central')
    local_time = pacific.fromutc(time_at_start_of_radar)
    fancy_date_string = local_time.strftime('%A %B %d at %I:%M %p %Z')
    print(fancy_date_string)

    metar_cat = TDSCatalog('http://thredds.ucar.edu/thredds/catalog/nws/metar/ncdecoded/catalog.xml?'
                           'dataset=nws/metar/ncdecoded/Metar_Station_Data_fc.cdmr')
    dataset = list(metar_cat.datasets.values())[0]
    ncss = NCSS(dataset.access_urls["NetcdfSubset"])

    query = ncss.query().accept('csv').time(time_at_start_of_radar)
    query.lonlat_box(north=max_lat, south=min_lat, east=max_lon, west=min_lon)
    query.variables('air_temperature', 'dew_point_temperature', 'inches_ALTIM',
                    'wind_speed', 'wind_from_direction', 'cloud_area_fraction', 'weather')
    data = ncss.get_data(query)

    lats = data['latitude'][:]
    lons = data['longitude'][:]
    tair = data['air_temperature'][:]
    dewp = data['dew_point_temperature'][:]
    slp = (data['inches_ALTIM'][:] * units('inHg')).to('mbar')

    # Convert wind to components
    u, v = mpcalc.get_wind_components(data['wind_speed'] * units.knot,
                                      data['wind_from_direction'] * units.deg)

    # Need to handle missing (NaN) and convert to proper code
    cloud_cover = 8 * data['cloud_area_fraction']
    cloud_cover[np.isnan(cloud_cover)] = 9
    cloud_cover = cloud_cover.astype(np.int)

    # For some reason these come back as bytes instead of strings
    stid = [s.decode() for s in data['station']]

    # Convert the text weather observations to WMO codes we can map to symbols
    #wx_text = [s.decode('ascii') for s in data['weather']]
    #wx_codes = np.array(list(to_code(wx_text)))

    sfc_data = {'latitude': lats, 'longitude': lons,
                'air_temperature': tair, 'dew_point_temperature': dewp, 'eastward_wind': u,
                'northward_wind': v, 'cloud_coverage': cloud_cover,
                'air_pressure_at_sea_level': slp}#, 'present_weather': wx_codes}

    fig = plt.figure(figsize=(10, 8))
    display = pyart.graph.RadarMapDisplayCartopy(radar)
    lat_0 = display.loc[0]
    lon_0 = display.loc[1]

    # Set our Projection
    projection = cartopy.crs.Mercator(central_longitude=lon_0,
                                      min_latitude=min_lat, max_latitude=max_lat)

    # Call our function to reduce data
    filter_data(sfc_data, projection, radius=station_radius, sort_key='present_weather')
    print(sweep)
    display.plot_ppi_map(
        field, sweep, colorbar_flag=True,
        title=radar_title +' area ' + field + ' \n' + fancy_date_string,
        projection=projection,
        min_lon=min_lon, max_lon=max_lon, min_lat=min_lat, max_lat=max_lat,
        vmin=vmin, vmax=vmax)

    # Mark the radar
    display.plot_point(lon_0, lat_0, label_text='Radar')

    # Get the current axes and plot some lat and lon lines
    gl = display.ax.gridlines(draw_labels=True,
                              linewidth=2, color='gray', alpha=0.5, linestyle='--')
    gl.xlabels_top = False
    gl.ylabels_right = False

    # Make the station plot
    stationplot = StationPlot(display.ax, sfc_data['longitude'], sfc_data['latitude'],
                              transform=cartopy.crs.PlateCarree(),
                              fontsize=12)
    station_layout.plot(stationplot, sfc_data)

    return display, time_at_start_of_radar
Beispiel #39
0
    sounding_data = fall_soundings.loc[ (fall_soundings[cols[1]]==mo) & (fall_soundings[cols[0]]==yr) & (fall_soundings[cols[2]]==day)]

T = convert_temperature(sounding_data[cols[6]].values,'F','C')
rh = sounding_data[cols[8]].values
sounding_data[cols[7]] = calc_dewpt(T,rh)
sounding_data = sounding_data.dropna(subset = (' Temp', ' Dewpt'),how='all').reset_index(drop=True)

hours = [np.min(sounding_data[cols[3]]), np.max(sounding_data[cols[3]])]
for i in range(len(hours)):
    one_sounding = sounding_data.loc[sounding_data[cols[3]]==hours[i]]
    T = convert_temperature(one_sounding[cols[6]].values,'F','C') * units.degC
    p = one_sounding[cols[5]].values * units.hPa
    Td = one_sounding[cols[7]].values * units.degC
    wind_speed = one_sounding[cols[-3]].values * units.knots
    wind_dir = one_sounding[cols[-2]].values * units.degrees
    u, v = mpcalc.get_wind_components(wind_speed, wind_dir)

    plt.rcParams['figure.figsize'] = (9, 9)

    skew = SkewT()
    skew.plot(p,T,'r')
    skew.plot(p,Td,'g')
    skew.plot_barbs(p,u,v)

    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()
    skew.ax.set_ylim(1000, 100)

    plt.title('OAK Sounding: '+ str(mo) + '/' + str(day) + '/' + str(yr) +': ' +str(int(hours[i]))+' UTC' )
    plt.savefig('images/OAK_sounding_'+ str(mo) + '_'+str(day) + '_' + str(yr) +'_' +str(int(hours[i]))+'UTC.pdf')