def calc_sounding_stats(_z, _th, _p, _qv): T = met.T(_th, _p) # T (K) pcl = met.CAPE(_z, _p, T, _qv, 1) # CAPE mupcl = met.CAPE(_z, _p, T, _qv, 2) # MUCAPE mlpcl = met.CAPE(_z, _p, T, _qv, 3) # MLCAPE return (pcl, mupcl, mlpcl)
def plot_sounding_data(filename, output): """Plot SkewT from a WRF / CM1 compatible sounding data file :param filename: The name of the file to open. :type filename: str :param output: The name of the file to output plot :type output: str The datafile is the same format as used in sounding initalization files for WRF and CM1. The format is: 1 line header with surface pressure (mb), theta (K) and qv (g/kg) n number of lines with z (m), theta (K), qv (g/kg), u (m/s), v(m/s) """ # load first line of file with open(filename, 'r') as f: surface = f.readline() p0, th0, qv0 = surface.split() # load rest of file _z, _th, _qv, _u, _v = np.loadtxt(filename, unpack=True, skiprows=1) # create arrays with one more z index for surface values nk = len(_z) + 1 z = np.empty(nk, np.float32) th = np.empty(nk, np.float32) qv = np.empty(nk, np.float32) u = np.empty(nk, np.float32) v = np.empty(nk, np.float32) p = np.empty(nk, np.float32) # copy the arrays, leaving room at the surface z[1:nk] = _z th[1:nk] = _th qv[1:nk] = _qv / 1000. u[1:nk] = _u v[1:nk] = _v # assign surface values z[0] = 0. th[0] = float(th0) qv[0] = float(qv0) / 1000. u[0] = 1.75 * u[1] - u[2] + 0.25 * u[3] v[0] = 1.75 * v[1] - v[2] + 0.25 * v[3] p[0] = float(p0) * 100. # integrate pressure, assume hydrostatic # dp = -rho*g*dz for k in np.arange(1, nk): p[k] = p[k - 1] * np.exp( (metconst.g * (z[k - 1] - z[k])) / (metconst.Rd * met.T( (th[k] + th[k - 1]) / 2., p[k - 1]))) #for k in np.arange(nk): # print(z[k], p[k], th[k], qv[k], u[k], v[k]) plot(None, z, th, p, qv, u, v, output, title="input sounding")
def draw_dry_adiabat(axes): """Plot dry adiabats on axes :parameter axes: The axes to draw on :type axes: :py:class:`matplotlib.axes` This function calculates dry adiabats and plots these lines. Adiabats are calculated every 10 K """ for T in dry_adiabats: dry_adiabat = met.T(T + met.T00, plevs_plot) - met.T00 + skew(plevs_plot) if (T % 10 == 0): axes.semilogy(dry_adiabat, plevs_plot, basey=math.e, color=lc_major, linewidth=lw_major) else: axes.semilogy(dry_adiabat, plevs_plot, basey=math.e, color=lc_minor, linewidth=lw_minor) for T in np.arange(-20, 150, 10): p = (600. - 3.5 * T) * 100. x = met.T(T + met.T00, p) - met.T00 + skew(p) x1 = met.T(T + met.T00, p + .5 * dp_plot) - met.T00 + skew(p + .5 * dp_plot) x2 = met.T(T + met.T00, p - .5 * dp_plot) - met.T00 + skew(p - .5 * dp_plot) dx = x2 - x1 theta = math.atan2(-dp_plot, -dx) * 180 / math.pi + 37 label(x, p / 100, str(T), 'black', theta, axes)
def plot_sounding(axes, z, th, p, qv, u=None, v=None): """Plot sounding data This plots temperature, dewpoint and wind data on a Skew-T/Log-P plot. This will also plot derived values such as wetbulb temperature and label the surface based LCL, LFC and EL. :parameter z: height values (1D array) :parameter th: potential temperature at z heights (1D array) :parameter p: pressure at z heights (1D array) :parameter qv: water vapor mixing ratio at z heights (1D array) :parameter u: U component of wind at z heights (1D array) :parameter v: V component of wind at z heights (1D array) :paramter axes: The axes instance to draw on """ # calculate Temperature and dewpoint T = met.T(th, p) - met.T00 # T (C) Td = met.Td(p, qv) - met.T00 # Td (C) # calculate wetbulb temperature Twb = np.empty(len(z), np.float32) # Twb (C) for zlvl in range(len(z)): Twb[zlvl] = met.Twb(z, p, th, qv, z[zlvl]) # Get surface parcel CAPE and temperature / height profiles pcl = met.CAPE(z, p, T + met.T00, qv, 1) # CAPE T_parcel = pcl['t_p'] - met.T00 # parcel T (C) T_vparcel = pcl['tv_p'] - met.T00 # parcel Tv (C) T_venv = met.T(pcl['thv_env'], pcl['pp']) - met.T00 # Env Tv (C) # plot Temperature, dewpoint, wetbulb and lifted surface parcel profiles on skew axes axes.semilogy(T + skew(p), p, basey=math.e, color=linecolor_T, linewidth=linewidth_T) axes.semilogy(Td + skew(p), p, basey=math.e, color=linecolor_Td, linewidth=linewidth_Td) axes.semilogy(T_parcel + skew(pcl['pp']), pcl['pp'], basey=math.e, color=linecolor_Parcel_T, linewidth=linewidth_Parcel_T) axes.semilogy(Twb + skew(p), p, basey=math.e, color=linecolor_Twb, linewidth=linewidth_Twb) # plot virtual temperature of environment and lifted parcel axes.semilogy(T_venv + skew(pcl['pp']), pcl['pp'], basey=math.e, color=linecolor_Tve, linewidth=linewidth_Tve, linestyle=linestyle_Tve) axes.semilogy(T_vparcel + skew(pcl['pp']), pcl['pp'], basey=math.e, color=linecolor_Tvp, linewidth=linewidth_Tvp, linestyle=linestyle_Tvp) # Add labels for levels based on surface parcel #debug print(pcl['lfcprs'], pcl['lclprs'], pcl['elprs'], pcl['ptops']) if (pcl['lfcprs'] > 0): label_m(Tmax - .5, pcl['lfcprs'], '--LFC', axes) if (pcl['lclprs'] > 0): label_m(Tmax - .5, pcl['lclprs'], '--LCL', axes) if (pcl['elprs'] > 0): label_m(Tmax - .5, pcl['elprs'], '--EL', axes) if (pcl['ptops'] > 0): label_m(Tmax - .5, pcl['ptops'], '--TOPS', axes) # plot labels for std heights for plvl in plevs_std: zlvl = pymeteo.interp.interp_height(z, p, plvl) label_m(Tmin - .5, plvl, str(int(zlvl)), axes) # plot wind barbs on left side of plot. move this? right side? if (u is not None and v is not None): #draw_wind_line(axes) for i in np.arange(0, len(z), 2): if (p[i] > pt_plot): plt.barbs(Tmin + 4, p[i], u[i], v[i], length=5, linewidth=.5)