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
def test_hodograph_units(): """Test passing unit-ed quantities to Hodograph.""" fig = plt.figure(figsize=(9, 9)) ax = fig.add_subplot(1, 1, 1) hodo = Hodograph(ax) u = np.arange(10) * units.kt v = np.arange(10) * units.kt hodo.plot(u, v) hodo.plot_colormapped(u, v, np.sqrt(u * u + v * v), cmap='Greys') return fig
def test_hodograph_wind_vectors(): """Test plotting wind vectors onto a hodograph.""" u_wind = np.array([-10, -7, 0, 7, 10, 7, 0, -7]) v_wind = np.array([0, 7, 10, 7, 0, -7, -10, -7]) fig = plt.figure(figsize=(6, 6)) ax = fig.add_subplot(1, 1, 1) h = Hodograph(ax, component_range=20) h.plot(u_wind, v_wind, linewidth=3) h.wind_vectors(u_wind, v_wind) return fig
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
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
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
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
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 = 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)') # Map - Oklahoma llcrnrlat = 33.6 urcrnrlat = 37.2 llcrnrlon = -103.2 urcrnrlon = -94.2 ax_map = fig5.add_subplot(gs[2, 2:]) m = Basemap(projection='merc', llcrnrlat=llcrnrlat,
def test_hodograph_alone(): """Test to create Hodograph without specifying axes.""" Hodograph()
# Create a new figure. The dimensions here give a good aspect ratio fig = plt.figure(figsize=(9, 9)) # 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()
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()
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()
# Create a new figure. The dimensions here give a good aspect ratio fig = plt.figure(figsize=(9, 9)) # Grid for plots 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) # 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(-30, 40) # Create a hodograph ax = fig.add_subplot(gs[0, -1]) h = Hodograph(ax, component_range=60.) h.add_grid(increment=20) h.plot(u, v) # Show the plot plt.show()
# 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()
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)
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.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)
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
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()
skew.plot(p, parcel_prof, 'k', linewidth=3) # 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))
def test_united_hodograph_range(): """Tests making a hodograph with a united ranged.""" fig = plt.figure(figsize=(6, 6)) ax = fig.add_subplot(1, 1, 1) Hodograph(ax, component_range=60. * units.knots)
# 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 ax_hod = inset_axes(skew.ax, '30%', '30%', loc=1) h = Hodograph(ax_hod, component_range=30.) h.add_grid(increment=20) # Add wind speed colored line cmap = ListedColormap(sns.cubehelix_palette(10, start=.5, rot=-.75)) levels = np.linspace(0, 20, 11) wind_speed_h = h.plot_colormapped(u, v, wind_speed, intervals=levels, cmap=cmap) # Add color bar for hodograph cbar_h = mpu.colorbar(wind_speed_h, ax_hod, orientation='vertical',
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')
skew.ax.set_xlim(-60, 40) skew.ax.set_ylim(1000, 100) skew.plot_dry_adiabats() skew.plot_moist_adiabats() skew.plot_mixing_lines() skew.ax.tick_params(axis='both', which='major', labelsize=15) skew.ax.set_xlabel('') skew.ax.set_ylabel('') #cape_cin #prof = mpcalc.parcel_profile(p, t[0], td[0]).to('degC') #skew.plot(p, prof, 'k', linewidth = 2) #skew.shade_cape(p, t, prof) lat = values[0].XLAT.values lon = values[0].XLONG.values utc = str(values[0].Time.values)[:-10] skew.ax.set_title('LAT : {:.5} | LON : {:.5}\n{}'.format(lat, lon, utc), fontsize=20) #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, metpy.calc.wind_speed(u, v)) plt.savefig(f'./SkewT_{utc}.png', bbox_inches='tight') plt.show()
#cambiando la direccion cardinal a angular angle = np.zeros(len(direction) + 2) #añado el dos para igualar size de ambas columnas #corregir #cambiar la denominacion: NS por NW for i in range(2, len(direction) + 2): angle[i] = portolan.middle(direction.direccion[i]) #5. GENERACIÓN DE LA HODOGRAFA angle = pd.DataFrame(angle[2:], columns=['angulo']) wind_speed = wind.values * units.knots wind_dir = angle.values * units.degrees u, v = mpcalc.wind_components(wind_speed, wind_dir) #visualizando la hodografa fig = plt.figure(figsize=(6, 6)) fig.suptitle('Hodografa - Estacion 000527') ax = fig.add_subplot(1, 1, 1) h = Hodograph(ax, component_range=10.) h.plot(u, v, linewidth=5) h.add_grid(increment=5) plt.savefig(dir_file + '/hodografa.png') #resultado: dado que la hodografa es casi constante en todo la figura #concluimos que la velocidad del viento es casi constante en modulo y direccion