def test_wet_bulb_temperature_1d(): """Test wet bulb calculation with 1d list.""" pressures = [1013, 1000, 990] * units.hPa temperatures = [25, 20, 15] * units.degC dewpoints = [20, 15, 10] * units.degC val = wet_bulb_temperature(pressures, temperatures, dewpoints) truth = [21.4449794, 16.7368576, 12.0656909] * units.degC # 21.58, 16.86, 12.18 from NWS Calculator assert_array_almost_equal(val, truth)
def test_wet_bulb_temperature_1d(): """Test wet bulb calculation with 1d list.""" pressures = [1013, 1000, 990] * units.hPa temperatures = [25, 20, 15] * units.degC dewpoints = [20, 15, 10] * units.degC val = wet_bulb_temperature(pressures, temperatures, dewpoints) truth = [21.4449794, 16.7368576, 12.0656909] * units.degC # 21.58, 16.86, 12.18 from NWS Calculator assert_array_almost_equal(val, truth)
def down_cape(p_start=None): if p_start not in ls.lev: raise ValueError( "Please provide pressure of one level of large-scale dataset to start calculating DCAPE from." ) # find index of p_start start_level = int((abs(ls.lev - p_start)).argmin()) # get temperature and humidity from large-scale state temp = ls.T.sel(lev=slice(None, 990)).metpy.unit_array mix = ls.r.sel(lev=slice(None, 990)).metpy.unit_array.to('kg/kg') p_vector = ls.lev.sel(lev=slice(None, 990)).metpy.unit_array # get dew-point temperature vap_pres = mpcalc.vapor_pressure(p_vector, mix) dew_temp = mpcalc.dewpoint(vap_pres) # pressure levels to integrate over p_down = ls.lev.sel(lev=slice(p_start, 990)) # find NaNs l_valid = ls.T[:, start_level].notnull().values d_cape = xr.full_like(ls.cape, np.nan) x = p_down.values temp = temp[l_valid, :] dew_temp = dew_temp[l_valid, :] # loop over all non-NaN times in large-scale state for i, this_time in enumerate(ls.T[l_valid].time): print(i) # bug: p_start has to be multiplied with units when given as argument, not beforehand wb_temp = mpcalc.wet_bulb_temperature(p_start * units['hPa'], temp[i, start_level], dew_temp[i, start_level]) # create placeholder for moist adiabat temperature moist_adiabat = temp[i, start_level:].to('degC') moist_adiabat_below = mpcalc.moist_lapse(p_vector[start_level + 1:], wb_temp, p_start * units['hPa']) moist_adiabat[0] = wb_temp moist_adiabat[1:] = moist_adiabat_below env_temp = temp[i, start_level:] temp_diff = moist_adiabat - env_temp y = temp_diff.magnitude d_cape.loc[this_time] = (mpconsts.Rd * (np.trapz(y, np.log(x)) * units.degK)).to( units('J/kg')) d_cape.attrs['long_name'] = 'Downward CAPE' return xr.merge([ls, xr.Dataset({'d_cape': d_cape})])
def _try_normand_wtb(s, t, d): # wrapper for metpy's implementation for cases where it doesn't converge # onto a solution (exceeds max iteration) so just return NaN try: return wet_bulb_temperature( np.array([s]) * units('hPa'), np.array([t]) * units('degC'), np.array([d]) * units('degC')).m except: return np.nan
def test_wet_bulb_temperature_2d(): """Test wet bulb calculation with 2d list.""" pressures = [[1013, 1000, 990], [1012, 999, 989]] * units.hPa temperatures = [[25, 20, 15], [24, 19, 14]] * units.degC dewpoints = [[20, 15, 10], [19, 14, 9]] * units.degC val = wet_bulb_temperature(pressures, temperatures, dewpoints) truth = [[21.4449794, 16.7368576, 12.0656909], [20.5021631, 15.801218, 11.1361878]] * units.degC # 21.58, 16.86, 12.18 # 20.6, 15.9, 11.2 from NWS Calculator assert_array_almost_equal(val, truth)
def test_wet_bulb_temperature_2d(): """Test wet bulb calculation with 2d list.""" pressures = [[1013, 1000, 990], [1012, 999, 989]] * units.hPa temperatures = [[25, 20, 15], [24, 19, 14]] * units.degC dewpoints = [[20, 15, 10], [19, 14, 9]] * units.degC val = wet_bulb_temperature(pressures, temperatures, dewpoints) truth = [[21.4449794, 16.7368576, 12.0656909], [20.5021631, 15.801218, 11.1361878]] * units.degC # 21.58, 16.86, 12.18 # 20.6, 15.9, 11.2 from NWS Calculator assert_array_almost_equal(val, truth)
def wetbulb_with_nan(pressure,temperature,dewpoint): ''' This function uses the MetPy wet_bulb_temperature method to calculate the actual wet bulb temperature using pressure, temperature, and dew point info. Inputs: pressure, temperature, dewpoint pint arrays Output: wetbulb_full pint array This function was constructed using code graciously suggested by Jon Thielen ''' nan_mask = np.isnan(pressure) | np.isnan(temperature) | np.isnan(dewpoint) idx = np.arange(pressure.size)[~nan_mask] wetbulb_valid_only = mpcalc.wet_bulb_temperature(pressure[idx], temperature[idx], dewpoint[idx]) wetbulb_full = np.full(pressure.size, np.nan) * wetbulb_valid_only.units wetbulb_full[idx] = wetbulb_valid_only return wetbulb_full
def calculate_sounding_data(df,field_height,field_temp): ###################################### CALCULATION MAGIC ################################################# # We will pull the data out of the latest soudning into individual variables and assign units. # # This will Return a dictionary with all the vallculate values. Keys are: # # "pressure", "temperature", "dewpoint", "height", "windspeed","wind_dir" ###################################### CALCULATION MAGIC ################################################# cache = settings.AppCache #Retrieves Sounding Details and returns them key='calculation'+str(field_height)+'_'+str(field_temp) #If soundings are cached and valid, returns the cache, otherwise retreive new sounding calc = cache.get(key) if calc is not None: logging.info("Calculation Cache Hit") print("Calculation Cahce Hit") return calc logging.info("Calculation Cache Miss") print("Calculation Cahce Miss") p = df['pressure'].values * units.hPa T = df['temperature'].values * units.degC Td = df['dewpoint'].values * units.degC alt = df['height'].values * units.ft wind_speed = df['speed'].values * units.knots wind_dir = df['direction'].values * units.degrees wet_bulb = mpcalc.wet_bulb_temperature(p,T,Td) field_pressure = mpcalc.height_to_pressure_std(field_height*units.ft) adiabat_line = mpcalc.dry_lapse(p,field_temp*units.degC,ref_pressure=mpcalc.height_to_pressure_std(field_height*units.ft)) #Interpolate Missing Values using linear interpolation Td_linear = interp1d(alt.magnitude,Td.magnitude) T_linear = interp1d(alt.magnitude,T.magnitude) #Calculate the LCL Based on Max Temperature lcl_pressure, lcl_temperature = mpcalc.lcl(field_pressure,field_temp*units.degC ,Td_linear(field_height)*units.degC) #parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC') calc = MeteoCast.UpperAtmData(df, p, T, Td,alt,wind_speed,wind_dir,wet_bulb,field_pressure,lcl_pressure,lcl_temperature,adiabat_line) cache.set(key, calc, expire=600,tag='Calculation Data ') return calc
#%% ########################################### # We will pull the data out of the example dataset into individual variables and # assign units. p = df_selected_time['pressure'].values * units.hPa T = df_selected_time['temperature'].values * units.degC Td = df_selected_time['dewpoint'].values * units.degC wind_speed = df_selected_time['speed'].values * units.knots wind_dir = df_selected_time[ 'direction'].values * units.degrees u, v = mpcalc.wind_components(wind_speed, wind_dir) # Calculate web bulb temperature df_selected_time[ 'wet_bulb_T'] = mpcalc.wet_bulb_temperature(p, T, Td) # Calculate potential temperature df_selected_time[ 'potential_T'] = mpcalc.potential_temperature(p, T) df_selected_time['potential_T_C'] = df_selected_time[ 'potential_T'].values - 273.15 # Calculate saturation vaper pressure df_selected_time[ 'saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure( T) df_selected_time[ 'vaper_pressure'] = mpcalc.saturation_vapor_pressure( Td) SVP = df_selected_time[
def test_wet_bulb_temperature(): """Test wet bulb calculation with scalars.""" val = wet_bulb_temperature(1000 * units.hPa, 25 * units.degC, 15 * units.degC) truth = 18.34345936 * units.degC # 18.59 from NWS calculator assert_almost_equal(val, truth)
def f(fullname, selected_time): fullname_el = fullname.split('/') #fullname_el = fullname.split('\\') filename = fullname_el[-1] filename_el = filename.split('_') save_base_dir_name = '../1data/' save_dir_name = '{0}{1}/'.format(save_base_dir_name + dir_name, obs_year) print('site : {0}'.format(dir_name)) if os.path.isfile('{0}{1}_{2}_student.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13]))\ and os.path.isfile('{0}{1}_{2}_solution.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13])): write_log(log_file, '{3} ::: {0}{1}_{2} files are already exist'\ .format(save_dir_name, filename_el[-5], selected_time[:13], datetime.now())) else: try: f = lambda s: selected_time in s ids = df['time'].apply(f) df_selected_time = df[ids] df_selected_time = df_selected_time.sort_values('pressure', ascending=False) print('filename : {0}'.format(fullname)) print('df_selected_time.\n{0}'.format(df_selected_time)) df_selected_time.to_csv(r'{0}{1}_{2}_student.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13])) ################################################################################# ### We will pull the data out of the example dataset into individual variables and ### assign units. ################################################################################# p = df_selected_time['pressure'].values * units.hPa T = df_selected_time['temperature'].values * units.degC Td = df_selected_time['dewpoint'].values * units.degC wind_speed = df_selected_time['speed'].values * units.knots wind_dir = df_selected_time['direction'].values * units.degrees u, v = mpcalc.wind_components(wind_speed, wind_dir) # Calculate web bulb temperature df_selected_time['wet_bulb_T'] = mpcalc.wet_bulb_temperature( p, T, Td) # Calculate potential temperature df_selected_time['potential_T'] = mpcalc.potential_temperature( p, T) df_selected_time['potential_T_C'] = df_selected_time[ 'potential_T'].values - 273.15 # Calculate saturation vaper pressure df_selected_time[ 'saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure( T) df_selected_time[ 'vaper_pressure'] = mpcalc.saturation_vapor_pressure(Td) SVP = df_selected_time[ 'saturation_vaper_pressure'].values * units.hPa VP = df_selected_time['vaper_pressure'].values * units.hPa # Calculate mixing ratio df_selected_time['saturation_mixing_ratio'] = mpcalc.mixing_ratio( SVP, p) df_selected_time['mixing_ratio'] = mpcalc.mixing_ratio(VP, p) SMR = df_selected_time['saturation_mixing_ratio'].values * units( 'g/kg') MR = df_selected_time['mixing_ratio'].values * units('g/kg') # Calculate relative humidity df_selected_time['relative_humidity_from_dewpoint'] \ = mpcalc.relative_humidity_from_dewpoint(T, Td) df_selected_time['relative_humidity_from_mixing_ratio'] \ = mpcalc.relative_humidity_from_mixing_ratio(MR, T, p) # Calculate virtual temperature df_selected_time['virtual_temperature'] \ = mpcalc.virtual_temperature(T, MR) # Calculate virtual potential temperature df_selected_time['virtual_potential_temperature'] \ = mpcalc.virtual_potential_temperature(p, T, MR) print('df_selected_time after drop nan.\n{0}'.format( df_selected_time)) df_selected_time.to_csv(r'{0}{1}_{2}_solution.csv'\ .format(save_dir_name, filename_el[-5], selected_time[:13])) except Exception as err: write_log(err_log_file, '{4} ::: {0} with {1}{2} on {3}'\ .format(err, dir_name, filename, selected_time[:13], datetime.now())) print('Thread {0} is finished'.format(selected_time)) return 0 # Return a dummy value
def plot_soundings(fig, ax, temp, rh, sfc_pressure, centerlat, centerlon, domainsize, model, cape=False, wetbulb=False): """ This function will plot a bunch of little soundings onto a matplotlib fig,ax. temp is an xarray dataarray with temperature data on pressure levels at least between 1000 and 300mb (you can change the ylimits for other datasets) rh is an xarray dataarray with temperature data on pressure levels at least between 1000 and 300mb (you can change ) sfc_pressure is an xarray dataarray with surface pressure data (NOT MSLP!) centerlat and centerlon are the coordinates around which you want your map to be centered. both are floats or integers and are in degrees of latitude and degrees of longitude west (i.e. 70W would be input as positive 70 here) domainsize is a string either 'local' for ~WFO-size domains or 'regional' for NE/SE/Mid-Atlantic-size domains (12 deg lat by 15 deg lon). More will be added soon. model is a string that specifies which model is providing data for the plots. This determines a few things, most importantly longitude selections. Models currently supported are 'GFS','NAM',and 'RAP' cape is a boolean to indicate whether you want to overlay parcel paths and shade CAPE/CIN on soundings with >100 J/kg of CAPE (this value can be changed) wetbulb is a boolean to indicate whether you want to draw wet bulb profiles note that this function doesn't "return" anything but if you just call it and provide the right arguments, it works. for example: import soundingmaps as smap ... smap.plot_soundings(fig,ax1,data['temperature'],data['rh'],30.5,87.5,'local',cape=True) """ r = 5 if domainsize == "local": init_lat_delt = 1.625 init_lon_delt = 0.45 lat_delts = [0.2, 0.7, 1.2, 1.75, 2.25, 2.8] londelt = 0.76 startlon = centerlon - 2 + 0.45 elif domainsize == "regional": init_lat_delt = 6 init_lon_delt = 1.6 lat_delts = [0.6, 2.5, 4.5, 6.4, 8.4, 10.25] londelt = 2.9 startlon = centerlon - 7.5 + 1.6 # Lon adjustment for GFS because it's [0,360] not [-180,180] if model == 'GFS': startlon = 360 - startlon # set lat/lon grid from which to pull data to plot soundings startlat = centerlat - init_lat_delt sound_lats = [] sound_lons = [] for i in range(0, 6): lats = startlat + lat_delts[i] sound_lats.append(lats) for i in range(0, r): if model == 'GFS': lons = startlon - (londelt * i) else: lons = -startlon - (londelt * i) sound_lons.append(lons) # this sets how high each row of soundings is on the plot plot_elevs = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7] # whole bunch of legend stuff dashed_red_line = lines.Line2D([], [], linestyle='solid', color='r', label='Temperature') dashed_purple_line = lines.Line2D([], [], linestyle='dashed', color='purple', label='0C Isotherm') dashed_green_line = lines.Line2D([], [], linestyle='solid', color='g', label='Dew Point') grey_line = lines.Line2D([], [], color='darkgray', label='MSLP (hPa)') blue_line = lines.Line2D([], [], color='b', label='Wet Bulb') pink_line = lines.Line2D([], [], color='fuchsia', label='Surface-Based Parcel Path') teal_line = lines.Line2D([], [], linestyle='dashed', color='teal', label='HGZ') green_dot = lines.Line2D([], [], marker='o', color='forestgreen', label='LCL') black_dot = lines.Line2D([], [], marker='o', color='k', label='Sounding Origin') red = mpatches.Patch(color='tab:red', label='CAPE') blue = mpatches.Patch(color='tab:blue', label='CIN') # do the plotting based on user inputs if cape and wetbulb is True: print('CAPE + Wetbulb') for i, plot_elev in enumerate(plot_elevs): soundlat = sound_lats[i] if k < 2: s = 1 else: s = 0 for i in range(s, r): levs_abv_ground = [] soundlon = sound_lons[i] sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15 sound_rh = rh.interp(lat=soundlat, lon=soundlon) sound_pres = temp.lev spres = sfc_pressure.interp(lat=soundlat, lon=soundlon) sound_dp = mpcalc.dewpoint_from_relative_humidity( sound_temps.data * units.degC, sound_rh.data * units.percent) sound_wb = mpcalc.wet_bulb_temperature( sound_pres, sound_temps.data * units.degC, sound_dp) #Only want data above the ground abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps, sound_pres)[0] abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp, sound_pres)[0] abv_sfc_wetb = spt.mask_below_terrain(spres, sound_wb, sound_pres)[0] pres_abv_ground = spt.mask_below_terrain( spres, sound_temps, sound_pres)[1] #sound_wb = sound_wb*units.degC skew = SkewT(fig=fig, rect=(0.75 - (0.15 * i), plot_elev, .15, .1)) parcel_prof = mpcalc.parcel_profile( pres_abv_ground, abv_sfc_temp[0].data * units.degC, abv_sfc_dewp[0]) cape = mpcalc.cape_cin(pres_abv_ground, abv_sfc_temp.data * units.degC, abv_sfc_dewp, parcel_prof) capeout = int(cape[0].m) cinout = int(cape[1].m) #skew.ax.axvspan(-30, -10, color='cyan', alpha=0.4) skew.plot(pres_abv_ground, abv_sfc_wetb, 'b', linewidth=2) skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3) skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3) if capeout > 100: # Shade areas of CAPE and CIN print(pres_abv_ground) print(abv_sfc_temp.data * units.degC) print(parcel_prof) skew.shade_cin(pres_abv_ground, abv_sfc_temp.data * units.degC, parcel_prof) skew.shade_cape(pres_abv_ground, abv_sfc_temp.data * units.degC, parcel_prof) skew.plot(pres_abv_ground, parcel_prof, color='fuchsia', linewidth=1) lcl_pressure, lcl_temperature = mpcalc.lcl( pres_abv_ground[0], abv_sfc_temp.data[0] * units.degC, abv_sfc_dewp[0]) skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='forestgreen') skew.ax.axvline(-30, color='teal', linestyle='--', linewidth=1) skew.ax.axvline(-10, color='teal', linestyle='--', linewidth=1) skew.plot(975, 0, 'ko', markerfacecolor='k') skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3) skew.ax.set_ylim((1000, 300)) skew.ax.axis('off') leg = ax.legend(handles=[ dashed_red_line, dashed_green_line, blue_line, dashed_purple_line, teal_line, green_dot, pink_line, red, blue, black_dot ], title='Sounding Legend', loc=4, framealpha=1) elif cape == True and wetbulb == False: print('CAPE no wetbulb') for k in range(len(plot_elevs)): soundlat = sound_lats[k] plot_elev = plot_elevs[k] if k == 0: s = 1 else: s = 0 for i in range(s, r): levs_abv_ground = [] soundlon = sound_lons[i] sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15 sound_rh = rh.interp(lat=soundlat, lon=soundlon) sound_pres = temp.lev spres = sfc_pressure.interp(lat=soundlat, lon=soundlon) sound_dp = mpcalc.dewpoint_from_relative_humidity( sound_temps.data * units.degC, sound_rh.data * units.percent) abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps, sound_pres)[0] abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp, sound_pres)[0] pres_abv_ground = spt.mask_below_terrain( spres, sound_temps, sound_pres)[1] skew = SkewT(fig=fig, rect=(0.75 - (0.15 * i), plot_elev, .15, .1)) parcel_prof = mpcalc.parcel_profile( pres_abv_ground, abv_sfc_temp[0].data * units.degC, abv_sfc_dewp[0]) cape = mpcalc.cape_cin(pres_abv_ground, abv_sfc_temp.data * units.degC, abv_sfc_dewp, parcel_prof) capeout = int(cape[0].m) cinout = int(cape[1].m) skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3) skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3) if capeout > 100: # Shade areas of CAPE and CIN skew.shade_cin(pres_abv_ground, abv_sfc_temp.data * units.degC, parcel_prof) skew.shade_cape(pres_abv_ground, abv_sfc_temp.data * units.degC, parcel_prof) skew.plot(pres_abv_ground, parcel_prof, color='fuchsia', linewidth=1) print(abv_sfc_temp) lcl_pressure, lcl_temperature = mpcalc.lcl( pres_abv_ground[0], abv_sfc_temp.data[0] * units.degC, abv_sfc_dewp[0]) skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='forestgreen') skew.ax.axvline(-30, color='teal', linestyle='--', linewidth=1) skew.ax.axvline(-10, color='teal', linestyle='--', linewidth=1) skew.plot(975, 0, 'ko', markerfacecolor='k') skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3) skew.ax.set_ylim((1000, 300)) skew.ax.axis('off') leg = ax.legend(handles=[ dashed_red_line, dashed_green_line, dashed_purple_line, teal_line, green_dot, pink_line, red, blue, black_dot ], title='Sounding Legend', loc=4, framealpha=1) elif wetbulb == True and cape == False: print('Wetbulb no CAPE') for k in range(len(plot_elevs)): soundlat = sound_lats[k] plot_elev = plot_elevs[k] if k == 0: s = 1 else: s = 0 for i in range(s, r): levs_abv_ground = [] soundlon = sound_lons[i] sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15 sound_rh = rh.interp(lat=soundlat, lon=soundlon) sound_pres = temp.lev spres = sfc_pressure.interp(lat=soundlat, lon=soundlon) sound_dp = mpcalc.dewpoint_from_relative_humidity( sound_temps.data * units.degC, sound_rh.data * units.percent) sound_wb = mpcalc.wet_bulb_temperature( sound_pres, sound_temps.data * units.degC, sound_dp) abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps, sound_pres)[0] abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp, sound_pres)[0] abv_sfc_wetb = spt.mask_below_terrain(spres, sound_wb, sound_pres)[0] pres_abv_ground = spt.mask_below_terrain( spres, sound_temps, sound_pres)[1] #sound_wb = sound_wb*units.degC skew = SkewT(fig=fig, rect=(0.75 - (0.15 * i), plot_elev, .15, .1)) skew.plot(pres_abv_ground, abv_sfc_wetb, 'b', linewidth=2) skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3) skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3) skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3) skew.ax.set_ylim((1000, 300)) skew.ax.axis('off') else: print('No Wetbulb or CAPE') for k in range(len(plot_elevs)): soundlat = sound_lats[k] plot_elev = plot_elevs[k] if k == 0: s = 1 else: s = 0 for i in range(s, r): sound_pres = temp.lev sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15 sound_rh = rh.interp(lat=soundlat, lon=soundlon) sound_dp = mpcalc.dewpoint_from_relative_humidity( sound_temps.data * units.degC, sound_rh.data * units.percent) skew = SkewT(fig=fig, rect=(0.75 - (0.15 * i), plot_elev, .15, .1)) skew.plot(sound_pres, sound_dp, 'g', linewidth=3) skew.plot(sound_pres, sound_temps, 'r', linewidth=3) skew.plot(1000, 0, 'ko', markerfacecolor='k') skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3) skew.ax.set_ylim((1000, 300)) skew.ax.axis('off') leg = ax.legend(handles=[ dashed_red_line, dashed_green_line, blue_line, dashed_purple_line, black_dot ], title='Sounding Legend', loc=4, framealpha=1)
.format(save_dir_name, filename_el[-5], selected_time[:13])) ################################################################################# ### We will pull the data out of the example dataset into individual variables and ### assign units. ################################################################################# p = df_selected_time['pressure'].values * units.hPa T = df_selected_time['temperature'].values * units.degC Td = df_selected_time['dewpoint'].values * units.degC wind_speed = df_selected_time['speed'].values * units.knots wind_dir = df_selected_time['direction'].values * units.degrees u, v = mpcalc.wind_components(wind_speed, wind_dir) # Calculate web bulb temperature df_selected_time['wet_bulb_T'] = mpcalc.wet_bulb_temperature(p, T, Td) # Calculate potential temperature df_selected_time['potential_T'] = mpcalc.potential_temperature(p, T) df_selected_time['potential_T_C'] = df_selected_time['potential_T'].values - 273.15 # Calculate saturation vaper pressure df_selected_time['saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure(T) df_selected_time['vaper_pressure'] = mpcalc.saturation_vapor_pressure(Td) SVP = df_selected_time['saturation_vaper_pressure'].values * units.hPa VP = df_selected_time['vaper_pressure'].values * units.hPa # Calculate mixing ratio df_selected_time['saturation_mixing_ratio'] = mpcalc.mixing_ratio(SVP, p) df_selected_time['mixing_ratio'] = mpcalc.mixing_ratio(VP, p) SMR = df_selected_time['saturation_mixing_ratio'].values * units('g/kg')
def test_wet_bulb_temperature(): """Test wet bulb calculation with scalars.""" val = wet_bulb_temperature(1000 * units.hPa, 25 * units.degC, 15 * units.degC) truth = 18.34345936 * units.degC # 18.59 from NWS calculator assert_almost_equal(val, truth)