def test_bunkers_motion(): """Test Bunkers storm motion with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') motion = concatenate(bunkers_storm_motion(data['pressure'], data['u_wind'], data['v_wind'], data['height'])) truth = [1.4537892577864744, 2.0169333025630616, 10.587950761120482, 13.915130377372801, 6.0208700094534775, 7.9660318399679308] * units('m/s') assert_almost_equal(motion.flatten(), truth, 8)
def test_bunkers_motion(): """Test Bunkers storm motion with observed sounding.""" data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC') motion = concatenate(bunkers_storm_motion(data['pressure'], data['u_wind'], data['v_wind'], data['height'])) truth = [2.18346161, 0.86094706, 11.6006767, 12.53639395, 6.89206916, 6.69867051] * units('m/s') assert_almost_equal(motion.flatten(), truth, 8)
def do_profile(cursor, fid, gdf, nt): """Process this profile.""" # The inbound profile may contain mandatory level data that is below # the surface. It seems the best we can do here is to ensure both # temperature and dewpoint are valid and call that the bottom. td_profile = gdf[pd.notnull(gdf["tmpc"]) & pd.notnull(gdf["dwpc"])] wind_profile = gdf[pd.notnull(gdf["u"])] # Presently we are all or nothing here. The length is arb if len(td_profile.index) < 5 or len(wind_profile.index) < 5: msg = ("quorum fail td: %s wind: %s, skipping") % ( len(td_profile.index), len(wind_profile.index), ) raise ValueError(msg) if gdf["pressure"].min() > 500: raise ValueError("Profile only up to %s mb" % (gdf["pressure"].min(), )) # Does a crude check that our metadata station elevation is within 50m # of the profile bottom, otherwise we ABORT station_elevation_m = get_station_elevation(td_profile, nt) # get surface wind u_sfc, v_sfc = get_surface_winds(wind_profile) u_1km, v_1km = get_aloft_winds(wind_profile, station_elevation_m + 1000.0) u_3km, v_3km = get_aloft_winds(wind_profile, station_elevation_m + 3000.0) u_6km, v_6km = get_aloft_winds(wind_profile, station_elevation_m + 6000.0) shear_sfc_1km_smps = np.sqrt((u_1km - u_sfc)**2 + (v_1km - v_sfc)**2) shear_sfc_3km_smps = np.sqrt((u_3km - u_sfc)**2 + (v_3km - v_sfc)**2) shear_sfc_6km_smps = np.sqrt((u_6km - u_sfc)**2 + (v_6km - v_sfc)**2) total_totals = compute_total_totals(td_profile) sweat_index = compute_sweat_index(td_profile, total_totals) try: bunkers_rm, bunkers_lm, mean0_6_wind = bunkers_storm_motion( wind_profile["pressure"].values * units.hPa, wind_profile["u"].values * units("m/s"), wind_profile["v"].values * units("m/s"), wind_profile["height"].values * units("m"), ) except ValueError: # Profile may not go up high enough bunkers_rm = [np.nan * units("m/s"), np.nan * units("m/s")] bunkers_lm = [np.nan * units("m/s"), np.nan * units("m/s")] mean0_6_wind = [np.nan * units("m/s"), np.nan * units("m/s")] bunkers_rm_smps = wind_speed(bunkers_rm[0], bunkers_rm[1]) bunkers_rm_drct = wind_direction(bunkers_rm[0], bunkers_rm[1]) bunkers_lm_smps = wind_speed(bunkers_lm[0], bunkers_lm[1]) bunkers_lm_drct = wind_direction(bunkers_lm[0], bunkers_lm[1]) mean0_6_wind_smps = wind_speed(mean0_6_wind[0], mean0_6_wind[1]) mean0_6_wind_drct = wind_direction(mean0_6_wind[0], mean0_6_wind[1]) try: ( srh_sfc_1km_pos, srh_sfc_1km_neg, srh_sfc_1km_total, ) = storm_relative_helicity( wind_profile["height"].values * units("m"), wind_profile["u"].values * units("m/s"), wind_profile["v"].values * units("m/s"), 1000.0 * units("m"), ) except ValueError: srh_sfc_1km_pos = np.nan * units("m") # blah srh_sfc_1km_neg = np.nan * units("m") # blah srh_sfc_1km_total = np.nan * units("m") # blah try: ( srh_sfc_3km_pos, srh_sfc_3km_neg, srh_sfc_3km_total, ) = storm_relative_helicity( wind_profile["height"].values * units("m"), wind_profile["u"].values * units("m/s"), wind_profile["v"].values * units("m/s"), 3000.0 * units("m"), ) except ValueError: srh_sfc_3km_pos = np.nan * units("m") # blah srh_sfc_3km_neg = np.nan * units("m") # blah srh_sfc_3km_total = np.nan * units("m") # blah pwater = precipitable_water( td_profile["pressure"].values * units.hPa, td_profile["dwpc"].values * units.degC, ) (sbcape, sbcin) = surface_based_cape_cin( td_profile["pressure"].values * units.hPa, td_profile["tmpc"].values * units.degC, td_profile["dwpc"].values * units.degC, ) (mucape, mucin) = most_unstable_cape_cin( td_profile["pressure"].values * units.hPa, td_profile["tmpc"].values * units.degC, td_profile["dwpc"].values * units.degC, ) (mlcape, mlcin) = mixed_layer_cape_cin( td_profile["pressure"].values * units.hPa, td_profile["tmpc"].values * units.degC, td_profile["dwpc"].values * units.degC, ) el_p, el_t = el( td_profile["pressure"].values * units.hPa, td_profile["tmpc"].values * units.degC, td_profile["dwpc"].values * units.degC, ) lfc_p, lfc_t = lfc( td_profile["pressure"].values * units.hPa, td_profile["tmpc"].values * units.degC, td_profile["dwpc"].values * units.degC, ) (lcl_p, lcl_t) = lcl( td_profile["pressure"].values[0] * units.hPa, td_profile["tmpc"].values[0] * units.degC, td_profile["dwpc"].values[0] * units.degC, ) vals = [ el_p.to(units("hPa")).m, lfc_p.to(units("hPa")).m, lcl_p.to(units("hPa")).m, ] [el_hght, lfc_hght, lcl_hght] = log_interp( np.array(vals, dtype="f"), td_profile["pressure"].values[::-1], td_profile["height"].values[::-1], ) el_agl = gt1(el_hght - station_elevation_m) lcl_agl = gt1(lcl_hght - station_elevation_m) lfc_agl = gt1(lfc_hght - station_elevation_m) args = ( nonull(sbcape.to(units("joules / kilogram")).m), nonull(sbcin.to(units("joules / kilogram")).m), nonull(mucape.to(units("joules / kilogram")).m), nonull(mucin.to(units("joules / kilogram")).m), nonull(mlcape.to(units("joules / kilogram")).m), nonull(mlcin.to(units("joules / kilogram")).m), nonull(pwater.to(units("mm")).m), nonull(el_agl), nonull(el_p.to(units("hPa")).m), nonull(el_t.to(units.degC).m), nonull(lfc_agl), nonull(lfc_p.to(units("hPa")).m), nonull(lfc_t.to(units.degC).m), nonull(lcl_agl), nonull(lcl_p.to(units("hPa")).m), nonull(lcl_t.to(units.degC).m), nonull(total_totals), nonull(sweat_index), nonull(bunkers_rm_smps.m), nonull(bunkers_rm_drct.m), nonull(bunkers_lm_smps.m), nonull(bunkers_lm_drct.m), nonull(mean0_6_wind_smps.m), nonull(mean0_6_wind_drct.m), nonull(srh_sfc_1km_pos.m), nonull(srh_sfc_1km_neg.m), nonull(srh_sfc_1km_total.m), nonull(srh_sfc_3km_pos.m), nonull(srh_sfc_3km_neg.m), nonull(srh_sfc_3km_total.m), nonull(shear_sfc_1km_smps), nonull(shear_sfc_3km_smps), nonull(shear_sfc_6km_smps), fid, ) cursor.execute( """ UPDATE raob_flights SET sbcape_jkg = %s, sbcin_jkg = %s, mucape_jkg = %s, mucin_jkg = %s, mlcape_jkg = %s, mlcin_jkg = %s, pwater_mm = %s, el_agl_m = %s, el_pressure_hpa = %s, el_tmpc = %s, lfc_agl_m = %s, lfc_pressure_hpa = %s, lfc_tmpc = %s, lcl_agl_m = %s, lcl_pressure_hpa = %s, lcl_tmpc = %s, total_totals = %s, sweat_index = %s, bunkers_rm_smps = %s, bunkers_rm_drct = %s, bunkers_lm_smps = %s, bunkers_lm_drct = %s, mean_sfc_6km_smps = %s, mean_sfc_6km_drct = %s, srh_sfc_1km_pos = %s, srh_sfc_1km_neg = %s, srh_sfc_1km_total = %s, srh_sfc_3km_pos = %s, srh_sfc_3km_neg = %s, srh_sfc_3km_total = %s, shear_sfc_1km_smps = %s, shear_sfc_3km_smps = %s, shear_sfc_6km_smps = %s, computed = 't' WHERE fid = %s """, args, )
def bunkers_storm_motion(self): return mpcalc.bunkers_storm_motion(self.p, self.u, self.v, self.z)