Esempio n. 1
0
def plot_sounding(date, station):
    p, T, Td, u, v, windspeed = get_sounding_data(date, station)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    lfc_pressure, lfc_temperature = mpcalc.lfc(p, T, Td)
    parcel_path = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')

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

    # Plot the data
    temperature_line, = skew.plot(p, T, color='tab:red')
    dewpoint_line, = skew.plot(p, Td, color='blue')
    cursor = mplcursors.cursor([temperature_line, dewpoint_line])

    # Plot thermodynamic parameters and parcel path
    skew.plot(p, parcel_path, color='black')

    if lcl_pressure:
        skew.ax.axhline(lcl_pressure, color='black')

    if lfc_pressure:
        skew.ax.axhline(lfc_pressure, color='0.7')

    # Add the relevant special lines
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    # Shade areas representing CAPE and CIN
    skew.shade_cin(p, T, parcel_path)
    skew.shade_cape(p, T, parcel_path)

    # Add wind barbs
    skew.plot_barbs(p, u, v)

    # Add an axes to the plot
    ax_hod = inset_axes(skew.ax, '30%', '30%', loc=1, borderpad=3)

    # Plot the hodograph
    h = Hodograph(ax_hod, component_range=100.)

    # Grid the hodograph
    h.add_grid(increment=20)

    # Plot the data on the hodograph
    mask = (p >= 100 * units.mbar)
    h.plot_colormapped(u[mask], v[mask], windspeed[mask])  # Plot a line colored by wind speed

    # Set some sensible axis limits
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    return fig, skew
Esempio n. 2
0
def test_hodograph_api():
    """Basic test of Hodograph API."""
    fig = plt.figure(figsize=(9, 9))
    ax = fig.add_subplot(1, 1, 1)
    hodo = Hodograph(ax, component_range=60)
    hodo.add_grid(increment=5, color='k')
    hodo.plot([1, 10], [1, 10], color='red')
    hodo.plot_colormapped(np.array([1, 3, 5, 10]), np.array([2, 4, 6, 11]),
                          np.array([0.1, 0.3, 0.5, 0.9]), cmap='Greys')
    return fig
Esempio n. 3
0
def test_hodograph_plot_colormapped():
    """Test hodograph colored line with NaN values."""
    u = np.arange(5., 65., 5)
    v = np.arange(-5., -65., -5)
    u[3] = np.nan
    v[6] = np.nan
    fig = plt.figure(figsize=(9, 9))
    ax = fig.add_subplot(1, 1, 1)
    hodo = Hodograph(ax, component_range=80)
    hodo.add_grid(increment=20, color='k')
    hodo.plot_colormapped(u, v, np.hypot(u, v), cmap='Greys')

    return fig
Esempio n. 4
0
def test_hodograph_plot_arbitrary_layer():
    """Test hodograph colored layers for arbitrary variables without interpolation."""
    u = np.arange(5, 65, 5) * units('knot')
    v = np.arange(-5, -65, -5) * units('knot')
    speed = np.sqrt(u ** 2 + v ** 2)
    colors = ['red', 'green', 'blue']
    levels = [0, 10, 20, 30] * units('knot')
    fig = plt.figure(figsize=(9, 9))
    ax = fig.add_subplot(1, 1, 1)
    hodo = Hodograph(ax, component_range=80)
    hodo.add_grid(increment=20, color='k')
    hodo.plot_colormapped(u, v, speed, bounds=levels, colors=colors)

    return fig
Esempio n. 5
0
def test_hodograph_plot_arbitrary_layer():
    """Test hodograph colored layers for arbitrary variables without interpolation."""
    u = np.arange(5, 65, 5) * units('knot')
    v = np.arange(-5, -65, -5) * units('knot')
    speed = np.sqrt(u**2 + v**2)
    colors = ['red', 'green', 'blue']
    levels = [0, 10, 20, 30] * units('knot')
    fig = plt.figure(figsize=(9, 9))
    ax = fig.add_subplot(1, 1, 1)
    hodo = Hodograph(ax, component_range=80)
    hodo.add_grid(increment=20, color='k')
    hodo.plot_colormapped(u, v, speed, bounds=levels, colors=colors)

    return fig
Esempio n. 6
0
def test_hodograph_plot_layers_bound_units():
    """Test hodograph colored height layers with interpolation and different units."""
    u = np.zeros((6)) * units.knots
    v = np.array([0, 10, 20, 30, 40, 50]) * units.knots
    heights = np.array([0, 1000, 2000, 3000, 4000, 5000]) * units.m
    bounds = np.array([0.5, 1.5, 2.5, 3.5, 4.5]) * units.km
    colors = ['r', 'g', 'b', 'r']
    fig = plt.figure(figsize=(7, 7))
    ax1 = fig.add_subplot(1, 1, 1)
    h = Hodograph(ax1)
    h.add_grid(increment=10)
    h.plot_colormapped(u, v, heights, colors=colors, bounds=bounds)
    ax1.set_xlim(-50, 50)
    ax1.set_ylim(-5, 50)
    return fig
Esempio n. 7
0
def test_hodograph_plot_layers_different_units():
    """Test hodograph colored height layers with interpolation and different units."""
    u = np.zeros(6) * units.knots
    v = np.array([0, 10, 20, 30, 40, 50]) * units.knots
    heights = np.array([0, 1, 2, 3, 4, 5]) * units.km
    intervals = np.array([500, 1500, 2500, 3500, 4500]) * units.m
    colors = ['r', 'g', 'b', 'r']
    fig = plt.figure(figsize=(7, 7))
    ax1 = fig.add_subplot(1, 1, 1)
    h = Hodograph(ax1)
    h.add_grid(increment=10)
    h.plot_colormapped(u, v, heights, colors=colors, intervals=intervals)
    ax1.set_xlim(-50, 50)
    ax1.set_ylim(-5, 50)
    return fig
Esempio n. 8
0
def test_hodograph_plot_layers_bound_units():
    """Test hodograph colored height layers with interpolation and different units."""
    u = np.zeros((6)) * units.knots
    v = np.array([0, 10, 20, 30, 40, 50]) * units.knots
    heights = np.array([0, 1000, 2000, 3000, 4000, 5000]) * units.m
    bounds = np.array([0.5, 1.5, 2.5, 3.5, 4.5]) * units.km
    colors = ['r', 'g', 'b', 'r']
    fig = plt.figure(figsize=(7, 7))
    ax1 = fig.add_subplot(1, 1, 1)
    h = Hodograph(ax1)
    h.add_grid(increment=10)
    h.plot_colormapped(u, v, heights, colors=colors, bounds=bounds)
    ax1.set_xlim(-50, 50)
    ax1.set_ylim(-5, 50)
    return fig
Esempio n. 9
0
def test_hodograph_plot_layers():
    """Test hodograph colored height layers with interpolation."""
    u = np.arange(5, 65, 5) * units('knot')
    v = np.arange(-5, -65, -5) * units('knot')
    h = [178, 213, 610, 656, 721, 914, 1060, 1219, 1372, 1412, 1512, 1524
         ] * units('meter')
    colors = ['red', 'green']
    levels = [0, 500, 1000] * units('meter')
    fig = plt.figure(figsize=(9, 9))
    ax = fig.add_subplot(1, 1, 1)
    hodo = Hodograph(ax, component_range=80)
    hodo.add_grid(increment=20, color='k')
    hodo.plot_colormapped(u, v, h, bounds=levels, colors=colors)

    return fig
Esempio n. 10
0
def plot_skewt(df):
    # We will pull the data out of the example dataset into individual variables
    # and assign units.
    hght = df['height'].values * units.hPa
    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.wind_components(wind_speed, wind_dir)

    # Create a new figure. The dimensions here give a good aspect ratio.
    fig = plt.figure(figsize=(9, 12))
    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()

    # Create a hodograph
    ax_hod = inset_axes(skew.ax, '40%', '40%', loc=2)
    h = Hodograph(ax_hod, component_range=80.)
    h.add_grid(increment=20)
    h.plot_colormapped(u, v, hght)

    return skew
Esempio n. 11
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
Esempio n. 12
0
 def process_skewt(self):
     # Calculation
     index_p100 = get_pressure_level_index(self.p_i, 100)
     lcl_p, lcl_t = mpcalc.lcl(self.p_i[0], self.t_i[0], self.td_i[0])
     lfc_p, lfc_t = mpcalc.lfc(self.p_i, self.t_i, self.td_i)
     el_p, el_t = mpcalc.el(self.p_i, self.t_i, self.td_i)
     prof = mpcalc.parcel_profile(self.p_i, self.t_i[0], self.td_i[0]).to('degC')
     cape, cin = mpcalc.cape_cin(self.p_i, self.t_i, self.td_i, prof)
     mucape, mucin = mpcalc.most_unstable_cape_cin(self.p_i, self.t_i, self.td_i)
     pwat = mpcalc.precipitable_water(self.td_i, self.p_i)
     i8 = get_pressure_level_index(self.p_i, 850)
     i7 = get_pressure_level_index(self.p_i, 700)
     i5 = get_pressure_level_index(self.p_i, 500)
     theta850 = mpcalc.equivalent_potential_temperature(850 * units('hPa'), self.t_i[i8], self.td_i[i5])
     theta500 = mpcalc.equivalent_potential_temperature(500 * units('hPa'), self.t_i[i5], self.td_i[i5])
     thetadiff = theta850 - theta500
     k = self.t_i[i8] - self.t_i[i5] + self.td_i[i8] - (self.t_i[i7] - self.td_i[i7])
     a = ((self.t_i[i8] - self.t_i[i5]) - (self.t_i[i8] - self.td_i[i5]) -
         (self.t_i[i7] - self.td_i[i7]) - (self.t_i[i5] - self.td_i[i5]))
     sw = c_sweat(np.array(self.t_i[i8].magnitude), np.array(self.td_i[i8].magnitude),
                  np.array(self.t_i[i5].magnitude), np.array(self.u_i[i8].magnitude),
                  np.array(self.v_i[i8].magnitude), np.array(self.u_i[i5].magnitude),
                  np.array(self.v_i[i5].magnitude))
     si = showalter_index(self.t_i[i8], self.td_i[i8], self.t_i[i5])
     li = lifted_index(self.t_i[0], self.td_i[0], self.p_i[0], self.t_i[i5])
     srh_pos, srh_neg, srh_tot = mpcalc.storm_relative_helicity(self.u_i, self.v_i, self.alt, 1000 * units('m'))
     sbcape, sbcin = mpcalc.surface_based_cape_cin(self.p_i, self.t_i, self.td_i)
     shr6km = mpcalc.bulk_shear(self.p_i, self.u_i, self.v_i, heights=self.alt, depth=6000 * units('m'))
     wshr6km = mpcalc.wind_speed(*shr6km)
     sigtor = mpcalc.significant_tornado(sbcape, delta_height(self.p_i[0], lcl_p), srh_tot, wshr6km)[0]
     # Plotting
     self.ax.set_ylim(1050, 100)
     self.ax.set_xlim(-40, 50)
     self.plot(self.p_i, self.t_i, 'r', linewidth=1)
     self.plot(self.p_i[:self.dp_idx], self.td_i[:self.dp_idx], 'g', linewidth=1)
     self.plot_barbs(self.p_i[:index_p100], self.u_i[:index_p100] * 1.94, self.v_i[:index_p100] * 1.94)
     self.plot(lcl_p, lcl_t, 'ko', markerfacecolor='black')
     self.plot(self.p_i, prof, 'k', linewidth=2)
     if cin.magnitude < 0:
         chi = -1 * cin.magnitude
         self.shade_cin(self.p_i, self.t_i, prof)
     elif cin.magnitude > 0:
         chi = cin.magnitude
         self.shade_cin(self.p_i, self.t_i, prof)
     else:
         chi = 0.
     self.shade_cape(self.p_i, self.t_i, prof)
     self.plot_dry_adiabats(linewidth=0.5)
     self.plot_moist_adiabats(linewidth=0.5)
     self.plot_mixing_lines(linewidth=0.5)
     plt.title('Skew-T Plot \nStation: {} Time: {}'.format(self.st, self.time.strftime('%Y.%m.%d %H:%M')), fontsize=14, loc='left')
     # Add hodograph
     ax = self._fig.add_axes([0.95, 0.71, 0.17, 0.17])
     h = Hodograph(ax, component_range=50)
     h.add_grid(increment=20)
     h.plot_colormapped(self.u_i[:index_p100], self.v_i[:index_p100], self.alt[:index_p100], linewidth=1.2)
     # Annotate parameters
     # Annotate names
     namelist = ['CAPE', 'CIN', 'MUCAPE', 'PWAT', 'K', 'A', 'SWEAT', 'LCL', 'LFC', 'EL', 'SI', 'LI', 'T850-500',
                 'θse850-500', 'SRH', 'STP']
     xcor = -50
     ycor = -90
     spacing = -9
     for nm in namelist:
         ax.text(xcor, ycor, '{}: '.format(nm), fontsize=10)
         ycor += spacing
     # Annotate values
     varlist = [cape, chi, mucape, pwat, k, a, sw, lcl_p, lfc_p, el_p, si, li, self.t_i[i8] - self.t_i[i5], thetadiff,
                srh_tot, sigtor]
     xcor = 10
     ycor = -90
     for v in varlist:
         if hasattr(v, 'magnitude'):
             v = v.magnitude
         ax.text(xcor, ycor, str(np.round_(v, 2)), fontsize=10)
         ycor += spacing
     # Annotate units
     unitlist = ['J/kg', 'J/kg', 'J/kg', 'mm', '°C', '°C', '', 'hPa', 'hPa', 'hPa', '°C', '°C', '°C', '°C']
     xcor = 45
     ycor = -90
     for u in unitlist:
         ax.text(xcor, ycor, ' {}'.format(u), fontsize=10)
         ycor += spacing
Esempio n. 13
0
skew.ax.set_xlim(-40, 60)

# 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)

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

# 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)
h = Hodograph(ax_hod, component_range=80.)
h.add_grid(increment=20)
h.plot_colormapped(u, v, wind_speed)  # Plot a line colored by wind speed

# Show the plot
plt.show()
Esempio n. 14
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
Esempio n. 15
0
pressure = df['pressure'].values * units(df.units['pressure'])
temperature = df['temperature'].values * units(df.units['temperature'])
wind_speed = df['speed'].values * units.knots
print(temperature)

dewpoint = df['dewpoint'].values * units(df.units['dewpoint'])
print(dewpoint)

u_wind = df['u_wind'].values * units(df.units['u_wind'])
print(u_wind)
v_wind = df['v_wind'].values * units(df.units['v_wind'])
heights = df['height'].values * units(df.units['height'])
print(mpcalc.wind_direction(u_wind,v_wind))
fig = plt.figure(figsize=(6,6))
ax = fig.add_subplot(1,1,1)
h= Hodograph(ax,component_range=60.)
h.plot(u_wind,v_wind,linewidth=5)
h.add_grid(increment=10)
#h.add_grid(increment=20,color='tab:orange',linestyle='-')
h.plot_colormapped(u_wind, v_wind, wind_speed)  # Plot a line colored by wind speed
plt.savefig('hodograph.png')
plt.show()
sys.exit()

#lcl_pressure, lcl_temperature = mpcalc.lcl(pressure[0], temperature[0], dewpoint[0])

#print(lcl_pressure, lcl_temperature)

# Calculate the parcel profile.
parcel_prof = mpcalc.parcel_profile(pressure, temperature[0], dewpoint[0]).to('degC')
Esempio n. 16
0
ax2.yaxis.tick_left()
ax2.tick_params(direction='in', pad=-5)

#PLOT PARCEL STUFF
plt.plot((37, 43), (mupcl.lfcpres,mupcl.lfcpres), 'r-',lw=1.5)
ax2.annotate('LFC', xy=(40, mupcl.lfcpres-10), xytext=(40, mupcl.lfcpres-10),ha='center', color='r')
plt.plot((37, 43), (mupcl.lclpres,mupcl.lclpres), 'g-',lw=1.5)
ax2.annotate('LCL', xy=(40, mupcl.lclpres+50), xytext=(40, mupcl.lclpres+50),ha='center', color='g')

# Create windbarbs and hodograph
skew.plot_barbs(p, u, v, xloc=1.1)
hgt_list = [0,3000,6000,9000,np.max(h)]
hodo_color = ['r','g','y','c']
hodo_label = ['0-3km','3-6km','6-9km','>9km']
ax_hod = inset_axes(skew.ax, '40%', '40%', loc=1)
for tick in ax_hod.xaxis.get_major_ticks():
    tick.label.set_fontsize(10)
    tick.label.set_rotation(45)
for tick in ax_hod.yaxis.get_major_ticks():
    tick.label.set_fontsize(10) 
hodo = Hodograph(ax_hod, component_range=80.)
hodo.add_grid(increment=20)
for k in range(len(hgt_list)-1):
    index1 = min(range(len(h)), key=lambda i: abs(h[i]-hgt_list[k]))
    index2 = min(range(len(h)), key=lambda i: abs(h[i]-hgt_list[k+1]))
    hodo.plot(u[index1:index2+1],v[index1:index2+1],c=hodo_color[k],linewidth=2.0,label=hodo_label[k])
ax_hod.legend(loc=2,prop={'size':8})

plt.savefig('/home/kgoebber/http/soundings/launches/'+launch+'_'+ascent+'/'+launch+'_'+ascent+'_KVUM.png',dpi=150)
#plt.show()
Esempio n. 17
0
def main():
    args = get_args()
    setup_logging(args["verbose"])

    # Define input file
    file = args["inputfile"]
    output = args["outputfile"]

    ds = xr.open_dataset(file)

    ds_sel = ds.isel({"sounding": 0})
    ds_sel = ds_sel.sortby(ds_sel.p, ascending=False)
    attrs = ds_sel.attrs
    ds_sel = ds_sel.metpy.quantify()

    p = ds_sel.p
    T = ds_sel.ta
    Td = ds_sel.dp
    wind_speed = ds_sel.wspd
    wind_dir = ds_sel.wdir
    ascend_rate = ds_sel.dz

    launch_time = attrs["time_of_launch_HHmmss"]
    platform = attrs["platform"]
    resolution = attrs["resolution"].replace(" ", "")

    # Filter nans
    idx = np.where(
        (np.isnan(T) + np.isnan(Td) + np.isnan(p) + np.isnan(wind_speed) +
         np.isnan(wind_dir)) is False,
        True,
        False,
    )
    p = p[idx].metpy.convert_units("hPa")
    T = T[idx].metpy.convert_units("degC")
    Td = Td[idx].metpy.convert_units("degC")
    wind_speed = wind_speed[idx].metpy.convert_units("meter / second")
    wind_dir = wind_dir[idx]

    u, v = mpcalc.wind_components(wind_speed, wind_dir)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])

    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0])
    parcel_prof = parcel_prof.metpy.convert_units("degC")

    direction = find_direction_of_sounding(ascend_rate)

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

    # 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")
    # Plot only specific barbs to increase visibility
    pressure_levels_barbs = np.logspace(0.1, 1, 50) * 100

    def find_nearest(array, value):
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return array[idx]

    # Search for levels by providing pressures
    # (levels is the coordinate not pressure)
    pres_vals = p.isel(level=idx)
    closest_pressure_levels = np.unique(
        [find_nearest(pres_vals, p_) for p_ in pressure_levels_barbs])
    _, closest_pressure_levels_idx, _ = np.intersect1d(pres_vals,
                                                       closest_pressure_levels,
                                                       return_indices=True)

    p_barbs = p.isel({"level": closest_pressure_levels_idx})
    wind_speed_barbs = wind_speed.isel({"level": closest_pressure_levels_idx})
    wind_dir_barbs = wind_dir.isel({"level": closest_pressure_levels_idx})
    u_barbs, v_barbs = mpcalc.wind_components(wind_speed_barbs, wind_dir_barbs)

    # Find nans in pressure
    skew.plot_barbs(p_barbs, u_barbs, v_barbs, xloc=1.06)

    skew.ax.set_ylim(1020, 100)
    skew.ax.set_xlim(-50, 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(pres_vals, parcel_prof, "k", linewidth=1.6)

    # Shade areas of CAPE and CIN
    skew.shade_cin(
        pres_vals.metpy.convert_units("hPa").values,
        T.metpy.convert_units("degC").values,
        parcel_prof.metpy.convert_units("degC").values,
    )
    skew.shade_cape(
        pres_vals.metpy.convert_units("hPa").values,
        T.metpy.convert_units("degC").values,
        parcel_prof.metpy.convert_units("degC").values,
    )

    # Plot a zero degree 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()

    # 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, "35%", "35%", loc=1)
    h = Hodograph(ax_hod, component_range=75.0)
    h.add_grid(increment=20)
    h.plot_colormapped(u, v, wind_speed)  # Plot a line colored by wind speed

    # Set title
    sounding_name = ds_sel.sounding.values
    sounding_name_str = str(sounding_name.astype("str"))
    skew.ax.set_title("{sounding}_{direction}".format(
        sounding=sounding_name_str, direction=direction))

    if output is None:
        filename_fmt = "{platform}_SoundingProfile_skew_{launch_time}_{res}.png".format(
            platform=platform, res=resolution, launch_time=launch_time)
        # filename_fmt = launch_time.strftime(filename_fmt)
        output = filename_fmt
    else:
        output = output.format(platform=platform,
                               direction=direction,
                               resolution=resolution)
        # output = launch_time.strftime(output)
    logging.info("Write output to {}".format(output))
    plt.savefig(output)
Esempio n. 18
0
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 = fig5.add_subplot(gs[:2, 2:])
#gs.tight_layout(fig5)
if np.nanmax(wind_kts) > 18:
    comprange = 35
else:
    comprange = 20

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

# Finland Map - ISOBAR
if mission == 'ISOBAR':
    # llcrnrlat = 33.6
    # urcrnrlat = 37.2
    # llcrnrlon = -103.2
    # urcrnrlon = -94.2
    lllat = 55.34
    urlat = 70.54
    lat_0 = 65.
    lon_0 = 24.
Esempio n. 19
0
def plot_skewt(snd: Sounding, save_to: Optional[str] = None, p_top: int = 100):
    """
    Plots a skew-T from the given Sounding.
    :param snd: The Sounding.
    :param save_to: Where to save the figure.  Default None, which does not save the figure, and instead shows it.
    :param p_top: Pressure at the top of the skew-T.  If you change this, Metpy might change the rotation of the
    isotherms.  No known fix yet.
    :return: None.
    """
    ####################################################################################################################
    # Data extraction and masking

    # Extract data from sounding.
    p = snd.p
    T = snd.T
    Td = snd.Td
    Tw = snd.Tw
    Te = snd.thetaE
    z = snd.z
    cf = snd["CFRL"]
    omega = snd.omega
    u, v = snd.wind_components()

    e = mpcalc.saturation_vapor_pressure(T)
    rv = mpcalc.mixing_ratio(e, p)
    w = mpcalc.vertical_velocity(omega, p, T, rv).to("cm/s")

    # Create masks to filter what data is plotted.
    mask_dewpoint = Td > -9000. * units.degC  # Plot only non-missing dewpoints.
    mask_wetbulb = Tw > -9000. * units.degC  # Plot only non-missing dewpoints.
    mask_thetae = Te > 0. * units.K  # Plot only non-missing theta-es.
    mask_barbs = p > p_top * units.hPa  # Plot only winds below the top of the sounding.

    ####################################################################################################################
    # Define intervals of height for coloring barbs and hodograph.
    z_interval_levels = [1500, 3000, 6000, 9000, 12000, 99999]
    z_interval_colors = ["red", "orange", "green", "blue", "purple", "grey"]

    z_colors = []

    for item in z:
        for color, interval in zip(z_interval_colors, z_interval_levels):
            if item <= interval * units.meter:
                z_colors.append(color)
                break

    ####################################################################################################################
    # Plotting skew-T

    fig = plt.figure(figsize=(11, 11))
    ax_hodo = fig.add_axes([0.70, 0.675, 0.25, 0.25])
    ax_thte = fig.add_axes([0.70, 0.375, 0.25, 0.25])
    skew = SkewT(fig, rotation=45, rect=[0.05, 0.05, 0.60, 0.9])

    # Plot temperature, dewpoint, and wet-bulb.
    skew.plot(p, T, 'r')
    skew.plot(p[mask_dewpoint], Td[mask_dewpoint], 'g')
    skew.plot(p[mask_wetbulb], Tw[mask_wetbulb], color='#009999', linewidth=1)

    # Calculate and plot surface parcel trace.
    sfc_trace = snd.parcel_trace(0).to('degC')
    sfc_trace_plot = skew.plot(p,
                               sfc_trace,
                               c='orange',
                               linewidth=2,
                               zorder=-10)

    # Calculate and plot MU parcel trace.
    mu_level_index = np.argmax(Te[p > 750. * units.hPa])
    mu_trace = snd.parcel_trace(mu_level_index).to('degC')
    mu_trace_plot = skew.plot(p[mu_level_index:],
                              mu_trace,
                              c='gray',
                              linewidth=2,
                              zorder=-9)

    # Plot each barb individually for control over color.  Unfortunately, the c arg of plot_barbs doesn't work for this
    # purpose.
    for p_, u_, v_, c_ in zip(p[mask_barbs][::BARB_DENSITY],
                              u[mask_barbs][::BARB_DENSITY],
                              v[mask_barbs][::BARB_DENSITY],
                              np.array(z_colors)[mask_barbs][::BARB_DENSITY]):
        skew.plot_barbs(p_, u_, v_, y_clip_radius=0.03, barbcolor=c_)

    ####################################################################################################################
    # Cloud fraction and omega
    zero_line = 1 / 15
    cf_plot = (cf * zero_line) / 100
    w_plot = (w.magnitude / 20) + zero_line
    skew.ax.plot(np.zeros(cf_plot.shape) + 1 / 15,
                 snd.p,
                 transform=skew.ax.get_yaxis_transform(),
                 color="grey")
    skew.ax.plot(cf_plot,
                 snd.p,
                 transform=skew.ax.get_yaxis_transform(),
                 color="black")
    skew.ax.plot(w_plot,
                 snd.p,
                 transform=skew.ax.get_yaxis_transform(),
                 color="purple")

    skew.ax.text(np.max(w_plot),
                 snd.p[np.argmax(w_plot)],
                 " {:.1f}".format(np.max(w.magnitude)),
                 color="purple",
                 ha="left",
                 va="center",
                 transform=skew.ax.get_yaxis_transform())
    skew.ax.text(max(np.min(w_plot), 0),
                 snd.p[np.argmin(w_plot)],
                 " {:.1f}".format(np.min(w.magnitude)),
                 color="purple",
                 ha="left",
                 va="center",
                 transform=skew.ax.get_yaxis_transform())
    # skew.ax.fill_betweenx(snd.p, cloud_fractions, np.zeros(cloud_fractions.shape))

    ####################################################################################################################
    # Tweaking

    skew.ax.set_xlim(-30, 40)
    skew.ax.set_ylim(1020, p_top)
    skew.ax.set_xlabel("")
    skew.ax.set_ylabel("")

    # Add legend for the parcel traces.
    skew.ax.legend(handles=[
        mlines.Line2D([], [], color='orange', label='Surface parcel'),
        mlines.Line2D([], [],
                      color='gray',
                      label=r"Max $\theta_e$ below 750mb"),
        mlines.Line2D([], [], color='black', label=r"Cloud fraction"),
        mlines.Line2D([], [],
                      color='purple',
                      label=r"Vertical velocity (cm/s)"),
    ],
                   loc="upper center")

    # Add adiabats and isohumes.
    skew.plot_dry_adiabats(t0=np.arange(233, 533, 10) * units.K,
                           alpha=0.25,
                           color='orangered')
    skew.plot_moist_adiabats(t0=np.arange(233, 400, 5) * units.K,
                             alpha=0.25,
                             color='tab:green')
    # Reshape required as a quirk of metpy.
    skew.plot_mixing_lines(w=np.array(
        [1, 2, 3, 4, 6, 8, 10, 12, 16, 20, 24, 28, 36]).reshape(-1, 1) / 1000.,
                           p=np.arange(1000, 99, -100) * units.hPa,
                           linestyle='dotted',
                           color='tab:blue')

    plt.title('RAP sounding at {}'.format(snd.params["STID"]), loc='left')
    plt.title('{:.0f}-hour forecast valid at {}'.format(
        snd.params["STIM"], snd.params["TIME"]),
              loc='right')

    ####################################################################################################################
    # Theta-E plot

    # Set up axis for theta-e plot.
    ax_thte.plot(Te[mask_thetae], p[mask_thetae])

    ax_thte.set_xlim(300, 360)
    ax_thte.set_ylim(1020, p_top)
    ax_thte.set_yscale("log")
    ax_thte.set_yticks(np.arange(p_top, 1001, 100))
    ax_thte.set_yticklabels(np.arange(p_top, 1001, 100))
    ax_thte.set_xlabel("")
    ax_thte.grid(axis="both")
    plt.text(0.5,
             0.9,
             "Theta-E (Kelvins)",
             ha="center",
             va="center",
             transform=ax_thte.transAxes)

    ####################################################################################################################
    # Hodograph

    # Set up axis for hodograph.
    h = Hodograph(ax_hodo, component_range=100)
    h.add_grid(20)

    # Plot each segment individually for control over color, reversed so that the full hodograph is plotted first,
    # followed by all but the last segment, etc.  Unfortunately, the plot_colormapped() function doesn't work for this
    # purpose.
    for color, interval in zip(reversed(z_interval_colors),
                               reversed(z_interval_levels)):
        mask = z < interval * units.meter
        h.plot(u.magnitude[mask], v.magnitude[mask], c=color)

    for vector in snd.bunkers_storm_motion():
        h.plot(vector[0], vector[1], c="black", markersize=3, marker="o")

    ax_hodo.set_xticks([])
    ax_hodo.set_yticks([])
    ax_hodo.set_xlim(-60, 100)
    ax_hodo.set_ylim(-60, 100)
    plt.text(0.1,
             0.9,
             "Velocity (knots)",
             ha="left",
             va="center",
             transform=ax_hodo.transAxes)
    for a in range(20, 61, 20):
        ax_hodo.text(-a * 0.71, -a * 0.71, a, ha="center", va="center")

########################################################################################################################
    parameter_names = ["SB STP", "0-1 SRH", "SB CAPE", "SB CIN"]
    parameters = [
        snd.significant_tornado()[0],
        snd.storm_relative_helicity()[2],
        snd.cape_cin(0)[0],
        snd.cape_cin(0)[1]
    ]

    for name, value, i in zip(parameter_names, parameters,
                              range(len(parameters))):
        s = "{:15} {:10.3f}".format(name, value.magnitude)
        fig.text(0.70,
                 0.32 - (0.02 * i),
                 s,
                 ha="left",
                 va="top",
                 family="monospace",
                 transform=fig.transFigure)

########################################################################################################################
    if save_to is None:
        plt.show()
    else:
        plt.savefig(save_to)
        plt.close()
Esempio n. 20
0
def skewt_plot(p,
               tc,
               tdc,
               t0,
               date,
               u=None,
               v=None,
               fout='sounding.png',
               latlon='',
               title='',
               show=False):
    """
   h: heights
   p: pressure
   tc: Temperature [C]
   tdc: Dew point [C]
   date: date of the forecast
   u,v: u,v wind components
   adapted from:
   https://geocat-examples.readthedocs.io/en/latest/gallery/Skew-T/NCL_skewt_3_2.html#sphx-glr-gallery-skew-t-ncl-skewt-3-2-py
   """
    Pmax = 150  # XXX upper limit
    print('Checking units')
    if p.attrs['units'] != 'hPa':
        print('P wrong units')
        exit()
    if tc.attrs['units'] != 'degC':
        print('Tc wrong units')
        exit()
    if tdc.attrs['units'] != 'degC':
        print('Tdc wrong units')
        exit()
    if t0.attrs['units'] != 'degC':
        print('T0 wrong units')
        exit()
    if type(u) != type(None) and type(v) != type(None):
        if u.attrs['units'] != 'm s-1':
            print('Wind wrong units')
            exit()
    LG.info('Inside skewt plot')
    p = p.values
    tc = tc.values
    tdc = tdc.values
    t0 = t0.mean().values
    u = u.values * 3.6  # km/h
    v = v.values * 3.6  # km/h
    # Grid plot
    LG.info('creating figure')
    fig = plt.figure(figsize=(11, 12))
    LG.info('created figure')
    LG.info('creating axis')
    gs = gridspec.GridSpec(1, 2, width_ratios=[4, 1])
    fig.subplots_adjust(wspace=0., hspace=0.)
    # ax1 = plt.subplot(gs[1:-1,0])
    # Adding the "rotation" kwarg will over-ride the default MetPy rotation of
    # 30 degrees for the 45 degree default found in NCL Skew-T plots
    LG.info('created axis')
    LG.info('Creatin SkewT')
    skew = SkewT(fig, rotation=45, subplot=gs[0, 0])
    ax = skew.ax
    LG.info('Created SkewT')

    if len(latlon) > 0:
        ax.text(0,
                1,
                latlon,
                va='top',
                ha='left',
                color='k',
                fontsize=12,
                bbox=dict(boxstyle="round", ec=None, fc=(1., 1., 1., 0.9)),
                zorder=100,
                transform=ax.transAxes)
    # Plot the data, T and Tdew vs pressure
    skew.plot(p, tc, 'C3')
    skew.plot(p, tdc, 'C0')
    LG.info('plotted dew point and sounding')

    # LCL
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0] * units.hPa,
                                               t0 * units.degC,
                                               tdc[0] * units.degC)
    skew.plot(lcl_pressure, lcl_temperature, 'k.')

    # Calculate the parcel profile  #XXX units workaround
    parcel_prof = mpcalc.parcel_profile(p * units.hPa, t0 * units.degC,
                                        tdc[0] * units.degC).to('degC')
    # Plot cloud base
    ind_cross = np.argmin(np.abs(parcel_prof.magnitude - tc))
    p_base = np.max([lcl_pressure.magnitude, p[ind_cross]])
    t_base = np.max([lcl_temperature.magnitude, tc[ind_cross]])
    m_base = mpcalc.pressure_to_height_std(np.array(p_base) * units.hPa)
    m_base = m_base.to('m').magnitude
    skew.ax.axhline(p_base, color=(0.5, 0.5, 0.5), ls='--')
    skew.plot(p_base, t_base, 'C3o', zorder=100)
    skew.ax.text(t_base, p_base, f'{m_base:.0f}m', ha='left')

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

    # shade CAPE and CIN
    skew.shade_cape(p * units.hPa, tc * units.degC, parcel_prof)
    skew.shade_cin(p * units.hPa, tc * units.degC, parcel_prof,
                   tdc * units.degC)
    LG.info('plotted CAPE and CIN')

    if type(u) != type(None) and type(v) != type(None):
        LG.info('Plotting wind')
        ax2 = plt.subplot(gs[0, 1], sharey=ax, zorder=-1)
        # ax2.yaxis.set_visible(False)
        ax2.yaxis.tick_right()
        # ax2.xaxis.tick_top()
        wspd = np.sqrt(u * u + v * v)
        ax2.scatter(wspd, p, c=p, cmap=HEIGHTS, zorder=10)
        gnd = mpcalc.pressure_to_height_std(np.array(p[0]) * units.hPa)
        gnd = gnd.to('m')
        # Ground
        ax2.axhline(p[0], c='k', ls='--')
        ax2.text(56,
                 p[0],
                 f'{int(gnd.magnitude)}m',
                 horizontalalignment='right')
        # Techo
        ax2.axhline(p_base, c=(0.5, 0.5, 0.5), ls='--')
        ### Background colors ##
        #for i,c in enumerate(WindSpeed.colors):
        #   rect = Rectangle((i*4, 150), 4, 900,  color=c, alpha=0.5,zorder=-1)
        #   ax2.add_patch(rect)
        #########################
        ax2.set_xlim(0, 56)
        ax2.set_xlabel('Wspeed (km/h)')
        ax2.grid()

        def p2h(x):
            """
         x in hPa
         """
            y = mpcalc.pressure_to_height_std(np.array(x) * units.hPa)
            # y = y.metpy.convert_units('m')
            y = y.to('m')
            return y.magnitude

        def h2p(x):
            """
         x in m
         """
            # x = x.values
            y = mpcalc.height_to_pressure_std(np.array(x) * units.m)
            # y = y.metpy.convert_units('hPa')
            y = y.to('hPa')
            return y.magnitude

        # print('------')
        # print(p[0])
        # print('---')
        # print(p2h(p[0]))
        # print('---')
        # print(h2p(p2h(p[0])))
        # print('------')
        # exit()

        ax2y = ax2.secondary_yaxis(1.02, functions=(p2h, h2p))
        ax2y.set_ylabel('height (m)')
        # ax2y.set_yticks(np.array([1000,2000,3000,4000,6000,6000,10000]))
        # XXX Not working
        ax2y.yaxis.set_major_formatter(ScalarFormatter())
        ax2y.yaxis.set_minor_formatter(ScalarFormatter())
        #################
        ax2y.set_color('red')
        ax2y.tick_params(colors='red', size=7, width=1,
                         which='both')  # 'both' refers to minor and major axes
        # ax2y.set_yticks([1,2,3,4])
        #ax2.set_xticks([0,5,10,15,20,30,40,50])
        #ax2.set_xticklabels(['0','','10','','20','30','40','50'])
        ax2.set_xticks([0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 56])
        ax2.set_xticklabels(
            ['0', '', '8', '', '16', '', '24', '32', '40', '48', '56'],
            fontsize=11,
            va='center')
        plt.setp(ax2.get_yticklabels(), visible=False)
        # Hodograph
        ax_hod = inset_axes(ax2, '110%', '30%', loc=1)
        ax_hod.set_yticklabels([])
        ax_hod.set_xticklabels([])
        L = 80
        ax_hod.text(0,
                    L - 5,
                    'N',
                    horizontalalignment='center',
                    verticalalignment='center')
        ax_hod.text(L - 5,
                    0,
                    'E',
                    horizontalalignment='center',
                    verticalalignment='center')
        ax_hod.text(-(L - 5),
                    0,
                    'W',
                    horizontalalignment='center',
                    verticalalignment='center')
        ax_hod.text(0,
                    -(L - 5),
                    'S',
                    horizontalalignment='center',
                    verticalalignment='center')
        h = Hodograph(ax_hod, component_range=L)
        h.add_grid(increment=20)
        h.plot_colormapped(
            -u, -v, p, cmap=HEIGHTS
        )  #'viridis_r')  # Plot a line colored by pressure (altitude)
        LG.info('Plotted wind')

        # # print('=-=-=-=-=-=-=')
        # # print(ax2.get_yscale())
        # # print(ax2y.get_yscale())
        # # print('=-=-=-=-=-=-=')
        # # ax2y.yaxis.tick_right()
        # # # ax2y.set_ylim(*reversed(ax.get_ylim()))
        # # ax2y.set_ylim(*ax.get_ylim())
        # # # calc pressure to height
        # # locs = ax2.get_yticks()
        # # labels = [mpcalc.pressure_to_height_std(h*units.hPa) for h in locs]
        # # labels = [round(l.to('m'),1) for l in labels]
        # # for xp,xh in zip(locs,labels):
        # #    print(xp,xh)
        # # ax2y.set_yticks(locs)
        # # ax2y.set_yticklabels([f'{int(l.magnitude)}' for l in labels])
        # Plot only every n windbarb
        n = 4
        inds, = np.where(p > Pmax)
        break_p = 25
        inds_low = inds[:break_p]
        inds_high = inds[break_p:]
        inds = np.append(inds_low[::n], inds_high)
        skew.plot_barbs(
            pressure=p[inds],  #[::n], # * units.hPa,
            u=u[inds],  #[::n],
            v=v[inds],  #[::n],
            xloc=0.985,  # fill_empty=True,
            sizes=dict(emptybarb=0.075, width=0.1, height=0.2))
    # #    # Draw line underneath wind barbs
    # #    line = mlines.Line2D([1.05, 1.05], [0, 1], color='gray', linewidth=0.5,
    # #                         transform=ax.transAxes,
    # #                         dash_joinstyle='round',
    # #                         clip_on=False,
    # #                         zorder=0)
    # #    ax.add_line(line)

    # Add relevant special lines
    # Choose starting temperatures in Kelvin for the dry adiabats
    LG.info('Plot adiabats, and other grid lines')
    skew.ax.text(t0, p[0], f'{t0:.1f}°C', va='top')
    skew.ax.axvline(t0, color=(0.5, 0.5, 0.5), ls='--')
    t0 = units.K * np.arange(243.15, 473.15, 10)
    skew.plot_dry_adiabats(t0=t0,
                           linestyles='solid',
                           colors='gray',
                           linewidth=1)

    # Choose temperatures for moist adiabats
    t0 = units.K * np.arange(281.15, 306.15, 4)
    msa = skew.plot_moist_adiabats(t0=t0,
                                   linestyles='solid',
                                   colors='lime',
                                   linewidths=.75)

    # Choose mixing ratios
    w = np.array([0.001, 0.002, 0.003, 0.005, 0.008, 0.012,
                  0.020]).reshape(-1, 1)

    # Choose the range of pressures that the mixing ratio lines are drawn over
    p_levs = units.hPa * np.linspace(1000, 400, 7)
    skew.plot_mixing_lines(mixing_ratio=w,
                           pressure=p_levs,
                           linestyle='dotted',
                           linewidths=1,
                           colors='lime')

    LG.info('Plotted adiabats, and other grid lines')

    skew.ax.set_ylim(1000, Pmax)
    skew.ax.set_xlim(-20, 43)
    # skew.ax.set_xlim(-30, 40)
    # XXX gvutil not installed
    # gvutil.set_titles_and_labels(ax, maintitle="ATS Rawinsonde: degC + Thin wind")
    # Set axes limits and ticks
    # gvutil.set_axes_limits_and_ticks(ax=ax, xlim=[-30, 50],
    #                 yticks=[1000, 850, 700, 500, 400, 300, 250, 200, 150, 100])

    # Change the style of the gridlines
    ax.grid(True,
            which='major',
            axis='both',
            color='tan',
            linewidth=1.5,
            alpha=0.5)

    ax.set_xlabel("Temperature (C)")
    ax.set_ylabel("P (hPa)")
    if len(title) == 0:
        title = f"{(date).strftime('%d/%m/%Y-%H:%M')} (local time)"
        ax.set_title(title, fontsize=20)
    else:
        ax.set_title(title, fontsize=20)
    if show: plt.show()
    LG.info('saving')
    fig.savefig(fout, bbox_inches='tight', pad_inches=0.1, dpi=150, quality=90)
    LG.info('saved')
    plt.close('all')
Esempio n. 21
0
# Shade areas of CAPE and CIN
skew.shade_cin(p, T, parcel_prof, Td)
skew.shade_cape(p, T, parcel_prof)

# Plot a zero degree isotherm
skew.ax.axvline(0, color='c', linestyle='--', linewidth=3)

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

ax1 = fig.add_subplot(gs[0:7, 4])
h = Hodograph(ax1, component_range=50.)
h.add_grid(increment=12.5)
h.plot(u, v, color='#0080ff')
ax1.tick_params(labelsize=15.)
ax1.set_xticks(np.arange(-50., 75., 25.))
ax1.set_yticks(np.arange(-50., 75., 25.))
ax1.set_xticklabels([])
ax1.set_title('Hodograph', fontsize=20.)
ax1.set_xlabel('wind speed ($m$ $s^{-1}$)', fontsize=15.)
ax1.set_ylabel('wind speed ($m$ $s^{-1}$)', fontsize=15.)

ax2 = fig.add_subplot(gs[9:15, 4])
[ax2.add_patch(PolygonPatch(shape, fc='none')) for shape in shapes]
ax2.scatter(lon[10:], lat[10:], c='r', s=10)
ax2.tick_params(labelsize=15.)
ax2.set_xticks(np.arange(119.5, 122., 0.5))
ax2.set_yticks(np.arange(22., 24.5, 0.5))
Esempio n. 22
0
# Create a new figure. The dimensions here give a good aspect ratio
fig = plt.figure(figsize=(9, 9))
add_metpy_logo(fig, 115, 100)

# Grid for plots
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)

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

# Good bounds for aspect ratio
skew.ax.set_xlim(-50, 60)

# Create a hodograph
ax_hod = inset_axes(skew.ax, '40%', '40%', loc=1)
h = Hodograph(ax_hod, component_range=80.)
h.add_grid(increment=20)
h.plot_colormapped(u, v, np.hypot(u, v))

# Show the plot
plt.show()
Esempio n. 23
0
    def _plot_hodograph(self, skew):

        # Create an array that indicates which layer (10-3, 3-1, 0-1 km) the
        # wind belongs to. The array, agl, will be set to the height
        # corresponding to the top of the layer. The resulting array will look
        # something like this:
        #
        #   agl = [1.0 1.0 1.0 3.0 3.0 3.0 10.0 10.0 10.0 10.87 ]
        #
        # Where the values above 10 km are unchanged, and there are three levels
        # in each of the 3 layers of interest.
        #
        agl = np.copy(self.atmo_profiles.get('gh', {}).get('data')).to('km')

        # Retrieve the wind data profiles
        u_wind = self.atmo_profiles.get('u', {}).get('data')
        v_wind = self.atmo_profiles.get('v', {}).get('data')

        # Create an inset axes object that is 28% width and height of the
        # figure and put it in the upper left hand corner.
        ax = inset_axes(skew.ax, '25%', '25%', loc=2)
        h = Hodograph(ax, component_range=80.)
        h.add_grid(increment=20, linewidth=0.5)

        intervals = [0, 1, 3, 10] * agl.units
        colors = ['xkcd:salmon', 'xkcd:aquamarine', 'xkcd:navy blue']
        line_width = 1.5

        # Plot the line colored by height AGL only up to the 10km level
        lines = h.plot_colormapped(
            u_wind,
            v_wind,
            agl,
            colors=colors,
            intervals=intervals,
            linewidth=line_width,
        )

        # Local function to create a proxy line object for creating a legend on
        # a LineCollection returned from plot_colormapped. Using lines and
        # colors from outside scope.
        def make_proxy(zval, idx=None, **kwargs):
            color = colors[idx] if idx < len(colors) else lines.cmap(zval - 1)
            return Line2D([0, 1], [0, 1],
                          color=color,
                          linewidth=line_width,
                          **kwargs)

        # Make a list of proxies
        proxies = [
            make_proxy(item, idx=i)
            for i, item in enumerate(intervals.magnitude)
        ]

        # Draw the legend
        ax.legend(
            proxies[:-1],
            ['0-1 km', '1-3 km', '3-10 km', ''],
            fontsize='small',
            loc='lower left',
        )
def main():
    args = get_args()
    setup_logging(args['verbose'])

    # Define input file
    file = args['inputfile']
    output = args['outputfile']

    ds = xr.open_dataset(file)

    ds_sel = ds.isel({'sounding': 0})
    ds_sel = ds_sel.sortby(ds_sel.pressure, ascending=False)

    p = ds_sel.pressure.values
    T = ds_sel.temperature.values
    Td = ds_sel.dewPoint.values
    wind_speed = ds_sel.windSpeed.values
    wind_dir = ds_sel.windDirection.values

    # Filter nans
    idx = np.where((np.isnan(T) + np.isnan(Td) + np.isnan(p) +
                    np.isnan(wind_speed) + np.isnan(wind_dir)) == False, True,
                   False)
    p = p[idx]
    T = T[idx]
    Td = Td[idx]
    wind_speed = wind_speed[idx]
    wind_dir = wind_dir[idx]

    # Add units
    p = p * units.hPa
    T = T * units.degC
    Td = Td * units.degC
    wind_speed = wind_speed * (units.meter / units.second)
    wind_dir = wind_dir * units.degrees

    u, v = mpcalc.wind_components(wind_speed, wind_dir)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])

    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')

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

    # 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')
    # Plot only specific barbs to increase visibility
    pressure_levels_barbs = np.logspace(0.1, 1, 50) * 100

    def find_nearest(array, value):
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return array[idx]

    # Search for levels by providing pressures
    # (levels is the coordinate not pressure)
    pres_vals = ds_sel.pressure.values[idx]
    closest_pressure_levels = np.unique(
        [find_nearest(pres_vals, p_) for p_ in pressure_levels_barbs])
    _, closest_pressure_levels_idx, _ = np.intersect1d(pres_vals,
                                                       closest_pressure_levels,
                                                       return_indices=True)

    p_barbs = ds_sel.pressure.isel({
        'levels': closest_pressure_levels_idx
    }).values * units.hPa
    wind_speed_barbs = ds_sel.windSpeed.isel({
        'levels':
        closest_pressure_levels_idx
    }).values * (units.meter / units.second)
    wind_dir_barbs = ds_sel.windDirection.isel({
        'levels':
        closest_pressure_levels_idx
    }).values * units.degrees
    u_barbs, v_barbs = mpcalc.wind_components(wind_speed_barbs, wind_dir_barbs)

    # Find nans in pressure
    # p_non_nan_idx = np.where(~np.isnan(pres_vals))
    skew.plot_barbs(p_barbs, u_barbs, v_barbs, xloc=1.06)

    # set axes limits:
    skew.ax.set_ylim(1020, 100)
    skew.ax.set_xlim(-50, 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(pres_vals, parcel_prof, 'k', linewidth=1.6)

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

    # Plot a zero degree 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()

    # 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, '35%', '35%', loc=1)
    h = Hodograph(ax_hod, component_range=75.)
    h.add_grid(increment=20)
    h.plot_colormapped(u, v, wind_speed)  # Plot a line colored by wind speed

    # Set title
    sounding_name = ds_sel.sounding.values
    sounding_name_str = str(sounding_name.astype('str'))
    skew.ax.set_title('{sounding}'.format(sounding=sounding_name_str))

    if output is None:
        output = str(os.path.basename(file).split('.')[0]) + '.pdf'
    logging.info('Write output to {}'.format(output))
    plt.savefig(output)