def add_metpy(option, filename): """ Adds the variables possible through metpy (theta, pv, n2) """ with xr.load_dataset(filename) as xin: if option.theta or option.pv: print("Adding potential temperature...") xin["pt"] = potential_temperature(xin["pressure"], xin["t"]) xin["pt"].data = np.array(xin["pt"].data) xin["pt"].attrs["units"] = "K" xin["pt"].attrs["standard_name"] = VARIABLES["pt"][2] if option.pv: print("Adding potential vorticity...") xin = xin.metpy.assign_crs(grid_mapping_name='latitude_longitude', earth_radius=6.356766e6) xin["pv"] = potential_vorticity_baroclinic(xin["pt"], xin["pressure"], xin["u"], xin["v"]) xin["pv"].data = np.array(xin["pv"].data * 10 ** 6) xin = xin.drop("metpy_crs") xin["pv"].attrs["units"] = "kelvin * meter ** 2 / kilogram / second" xin["pv"].attrs["standard_name"] = VARIABLES["pv"][2] xin["mod_pv"] = xin["pv"] * ((xin["pt"] / 360) ** (-4.5)) xin["mod_pv"].attrs["standard_name"] = VARIABLES["mod_pv"][2] if option.n2: print("Adding N2...") xin["n2"] = brunt_vaisala_frequency_squared(geopotential_to_height(xin["zh"]), xin["pt"]) xin["n2"].data = np.array(xin["n2"].data) xin["n2"].attrs["units"] = VARIABLES["n2"][1] xin["n2"].attrs["standard_name"] = "square_of_brunt_vaisala_frequency_in_air" xin.to_netcdf(filename)
def test_brunt_vaisala_frequency_squared(): """Test Brunt-Vaisala frequency squared function.""" truth = [[1.35264138e-04, 2.02896207e-04, 3.04344310e-04, 1.69080172e-04], [1.34337671e-04, 2.00818771e-04, 1.00409386e-04, 1.00753253e-04], [1.33423810e-04, 6.62611486e-05, 0, 1.33879181e-04], [1.32522297e-04, -1.99457288e-04, 0., 2.65044595e-04]] * units('s^-2') bv_freq_sqr = brunt_vaisala_frequency_squared(bv_data()[0], bv_data()[1]) assert_almost_equal(bv_freq_sqr, truth, 6)
def preprocessDataResample(file, path, spatialResolution, lambda1, lambda2, order): #delete gloabal data variable as soon as troubleshooting is complete """ prepare data for hodograph analysis. non numeric values & values > 999999 removed, brunt-viasala freq calculated, background wind removed Different background removal techniques used: rolling average, savitsky-golay filter, nth order polynomial fits """ data = openFile(file, path) data = interpolateVertically(data) #change data container name, sounds silly but useful for troubleshooting data-cleaning bugs global df df = data #print(df) #make following vars availabale outside of function - convenient for time being, but consider changing in future """ global Time global Pres global Temp global Hu global Wd global Long global Lat global Alt global potentialTemp global bv2 global u, v global uBackground global vBackground global tempBackground #for comparing rolling ave to savitsky golay #global uBackgroundRolling #global vBackgroundRolling #global tempBackgroundRolling #global uRolling #global vRolling #global tRolling """ #individual series for each variable, local Time = df['Time'].to_numpy() Pres = df['P'].to_numpy() * units.hPa Temp = df['T'].to_numpy() * units.degC Ws = df['Ws'].to_numpy() * units.m / units.second Wd = df['Wd'].to_numpy() * units.degree Long = df['Long.'].to_numpy() Lat = df['Lat.'].to_numpy() Alt = df['Alt'].to_numpy().astype(int) * units.meter #calculate brunt-viasala frequency **2 tempK = Temp.to('kelvin') potentialTemperature = tempK * (p_0 / Pres)**( 2 / 7) #https://glossary.ametsoc.org/wiki/Potential_temperature bv2 = mpcalc.brunt_vaisala_frequency_squared( Alt, potentialTemperature).magnitude #N^2 #bv2 = bruntViasalaFreqSquared(potentialTemperature, heightSamplingFreq) #Maybe consider using metpy version of N^2 ? Height sampling is not used in hodo method, why allow it to affect bv ? #convert wind from polar to cartesian c.s. u, v = mpcalc.wind_components( Ws, Wd) #raw u,v components - no different than using trig fuctions print("Size of u: ", len(u)) #subtract nth order polynomials to find purturbation profile return