コード例 #1
0
ファイル: test_thermo.py プロジェクト: Schmittyapolis/SHARPpy
def test_wetlift():
    input_p = 700
    input_t = 15
    input_p2 = 100
    correct_t = -81.27400812504021
    returned_t = thermo.wetlift(input_p, input_t, input_p2)
    npt.assert_almost_equal(returned_t, correct_t)
コード例 #2
0
ファイル: test_thermo.py プロジェクト: wyj901020/SHARPpy
def test_wetlift():
    input_p = 700
    input_t = 15
    input_p2 = 100
    correct_t = -81.27400812504021
    returned_t = thermo.wetlift(input_p, input_t, input_p2)
    npt.assert_almost_equal(returned_t, correct_t)
コード例 #3
0
ファイル: myskewt.py プロジェクト: ahijevyc/lib_python
def draw_background(ax,
                    dry=np.arange(-50, 110, 20),
                    moist=np.arange(-5, 40, 5),
                    presvals=np.arange(1050, 0, -10),
                    mix=[1, 2, 4, 8, 12, 16, 20, 24]):

    # Plot dry adiabats
    for t in dry:
        ax.semilogy(thetas(t, presvals),
                    presvals,
                    'r-',
                    alpha=0.2,
                    linewidth=1)

    # Plot moist adiabats to topp
    topp = 200
    moist_presvals = np.arange(np.max(presvals), topp, -10)
    for t in moist:
        tw = []
        for p in moist_presvals:
            tw.append(thermo.wetlift(1000., t, p))
        ax.semilogy(tw,
                    moist_presvals,
                    'k-',
                    alpha=0.2,
                    linewidth=0.5,
                    linestyle='dashed')
        # add moist adiabat text labels
        ax.text(thermo.wetlift(1000., t, topp + 15),
                topp + 15,
                t,
                va='center',
                ha='center',
                size=5.6,
                alpha=0.3,
                clip_on=True)

    # Mixing ratio lines and labels to topp

    topp = 650
    for w in mix:
        ww = []
        for p in presvals:
            ww.append(thermo.temp_at_mixrat(w, p))
        ax.semilogy(ww,
                    presvals,
                    'g',
                    alpha=0.35,
                    linewidth=1,
                    linestyle="dotted")
        ax.text(thermo.temp_at_mixrat(w, topp),
                topp,
                w,
                va='bottom',
                ha='center',
                size=6.7,
                color='g',
                alpha=0.35)

    # Disables the log-formatting (10 to the power of x) that comes with semilogy
    ax.yaxis.set_major_formatter(plt.ScalarFormatter())
    ax.set_yticks(np.linspace(100, 1000, 10))
    ax.set_ylim(1050, 100)
    plt.ylabel('Pressure (hPa)')

    # The first time this axis object is returned, no xtick gridlines show up for -110 to -60C
    ax.xaxis.set_major_locator(plt.MultipleLocator(10))
    ax.set_xlim(-50, 45)
    plt.xlabel('Temperature (C)')

    ax.grid(True, linestyle='solid', alpha=0.5)
コード例 #4
0
def plot_wof(prof, members, figname, xlat, xlon, idateobj, vdateobj, **kwargs):
    #    '''
    #    Plots SHARPpy SPC window as .png
    #
    #    Parameters
    #    ----------
    #    prof : a Profile Object from sharppy.sharptab.profile
    #
    #    kwargs
    #    ------
    #    parcel_type: Parcel choice for plotting. 'sfc','ml','mu','fcst' Default is 'ml'
    #    filename: Filename as a string. Default is 'sounding.png'
    #    logo: Logo for upper-left portion of the skew-t. Default is 'None' and does not plot a logo.
    #    logo_dxdy: Size of logo. Actual dimensions are dT and dp as it is plotted on the skewT. Default is (20,13) This worked for a 489x132 pixel image.
    #    '''
    #kwargs
    parcel_type = kwargs.get('parcel_type', 'ml')
    xpts = kwargs.get('x_pts')
    ypts = kwargs.get('y_pts')

    #Figure User Input

    p_grid_labels = [
        '1000', '', '', '850', '', '', '700', '', '', '', '500', '', '', '',
        '300', '', '200', '', '100'
    ]  #labels for the pressure ticks. Standard.
    p_grid = [1000, 850, 700, 500, 300, 200,
              100]  #where horizontal lines go across the skew-T

    my_dpi = 55  #dots per inch for the plot. This is a pretty hi-res image.

    pmax = 1050  #lowest pressure on the skew-T
    pmin = 100  #highest pressure on the skew-T
    dp = -10  #pressure spacing for creating skew-T background lines

    presvals = np.arange(
        int(pmax),
        int(pmin) + dp,
        dp)  #pressure values used for creating skew-T background lines

    # Colors for wind speed bars and hodograph
    hgt_list_bar = [0, 1000, 3000, 6000, 9000, 20000]
    hgt_list_hodo = [0, 1000, 3000, 6000, 9000, 10000]

    hodo_color = [
        cb_colors.orange6, cb_colors.green6, cb_colors.blue6,
        cb_colors.purple6, cb_colors.red6
    ]
    hodo_label = ['0-1km', '1-3km', '3-6km', '6-9km', '9-10km']

    #convoluted mess to get the title to be aligned how I wanted. This should be changed for others...
    spaces = 10  #22
    #   title_text_1 = '' #site + ' ' + dt.strftime('%Y/%m/%d %H:%M UTC ' + data_type)
    #   title_text_3 = 'Sounding Powered by SHARPpy'
    sharptext = 'Sounding Powered by SHARPpy'
    #   title_text_2 = title_text_3 = ''
    title_text_3 = 'WoFS Sounding {}N, {}W'.format(
        xlat, xlon) + (' ' * spaces) + 'Init: {}     Valid: {}'.format(
            idateobj.strftime('%Y-%m-%d %H%M UTC'),
            vdateobj.strftime('%Y-%m-%d %H%M UTC'))
    #xlat, xlon, initdate, validdate
    title_text = title_text_3  #title_text_1 + (' '*spaces) +title_text_2 + (' '*spaces) + title_text_3

    #Figures out where at which height the sounding reached in the list of h_new
    #Then interpolates pressure to height levels
    h_new = [0, 1000, 3000, 6000, 9000, 12000, 15000]

    for i in range(len(h_new)):
        if np.max(prof.hght) > h_new[i]:
            index = i
    h_new_labels = ['0 km', '1 km', '3 km', '6 km', '9 km', '12 km', '15 km']
    h_new_labels = h_new_labels[0:index + 1]
    #p_interped_func = interpolate.interp1d(prof.hght, prof.pres)

    p_interped = sharptab.interp.pres(
        prof, sharptab.interp.to_msl(prof, h_new[0:index + 1]))

    #Thin out the winds for better plotting (significant level data points seem to bunch together to closely
    minimum_separation = 250.  #minimum spacing between wind barbs (meters)
    h_barb = np.array(prof.hght).tolist()
    p_barb = np.array(prof.pres).tolist()
    spd_barb = np.array(prof.wspd).tolist()
    direc_barb = np.array(prof.wdir).tolist()

    #adds units to our newly created pressure, speed, and direction arrays for wind barb plotting
    #p_barb = p_barb * units.mbar
    #spd_barb = spd_barb * units.knot
    #direc_barb = direc_barb * units.deg

    # Convert wind speed and direction to components
    #u, v = get_wind_components(prof.wspd * units.knot, prof.wdir * units.deg)
    u, v = utils.vec2comp(prof.wdir, prof.wspd)
    u_barb, v_barb = utils.vec2comp(prof.wdir, prof.wspd)

    #SELECT PARCEL AND GET PARCEL DATA FROM SPC_UTILS
    sfcpcl = prof.sfcpcl  #params.parcelx( prof, flag=1 )
    fcstpcl = prof.fcstpcl  #params.parcelx( prof, flag=2)
    mupcl = prof.mupcl  #params.parcelx( prof, flag=3 )
    mlpcl = prof.mlpcl  #params.parcelx( prof, flag=4 )
    if parcel_type == 'sfc':
        pcl = sfcpcl
        pcl_box_level = -0.065
        pcl_type = 1
    elif parcel_type == 'fcst':
        pcl = fcstpcl
        pcl_box_level = -0.0875
        pcl_type = 2
    elif parcel_type == 'mu':
        pcl = mupcl
        pcl_box_level = -0.1325
        pcl_type = 4
    elif parcel_type == 'ml':
        pcl = mlpcl
        pcl_box_level = -0.11
        pcl_type = 3
    else:
        print(
            "ERROR! Select 'sfc', 'fcst', 'mu', or 'ml' for parcel type. (plot_spc(prof,parcel_type)"
        )
        print("Defaulting to surface parcel...")
        pcl = sfcpcl
        pcl_box_level = -0.065

#PLOTTING *************************************************************************************************************

#Create full figure
    fig = plt.figure(figsize=(1180 / my_dpi, 800 / my_dpi),
                     dpi=my_dpi,
                     frameon=False)

    #SKEW T ***************************************************
    ax = fig.add_subplot(111, projection='skewx',
                         facecolor="w")  #skewed x-axis

    # plot dashed temperature lines
    ax.xaxis.grid(color='k',
                  linestyle='--',
                  dashes=(3, 3),
                  alpha=0.5,
                  zorder=0)

    # plot the moist-adiabats
    for temp in np.arange(-10, 45, 5):
        tw = []
        for pres in presvals:
            tw.append(thermo.wetlift(1050., temp, pres))
        ax.semilogy(tw,
                    presvals,
                    color=cb_colors.purple6,
                    linestyle='--',
                    dashes=(5, 2),
                    alpha=.3)  #cb_colors.purple6

# plot the dry adiabats
    for t in np.arange(-50, 80, 20):
        thetas = ((t + thermo.ZEROCNK) / (np.power(
            (1000. / presvals), thermo.ROCP))) - thermo.ZEROCNK
        ax.semilogy(thetas, presvals, 'k', alpha=.3)

#plot mixing ratio lines
    mixing_ratio_list = range(6, 36, 4)
    for mr in mixing_ratio_list:
        plt.plot((thermo.temp_at_mixrat(mr, 1050) - 273,
                  thermo.temp_at_mixrat(mr, 600) - 273), (1050, 600),
                 'g-',
                 lw=1.0,
                 zorder=3,
                 alpha=0.6)
        ax.annotate(str(mr),
                    xy=((thermo.temp_at_mixrat(mr, 600) - 273), (600 - 3)),
                    xytext=((thermo.temp_at_mixrat(mr, 600) - 273), (600 - 3)),
                    ha='center',
                    color='g',
                    family='sans-serif',
                    weight='bold',
                    zorder=3,
                    fontsize=10,
                    alpha=0.6)

#plot horizontal lines at standard pressure levels
    for p_loc in p_grid:
        ax.axhline(y=p_loc, ls='-', c='k', alpha=0.5, linewidth=1.5, zorder=3)

# PLOT THE DATA ON THE SKEW-T

# Plot the data using normal plotting functions, in this case using log scaling in Y, as dicatated by the typical meteorological plot

    ax.semilogy(prof.wetbulb,
                prof.pres,
                c="c",
                linestyle='-',
                lw=1,
                alpha=1.0,
                zorder=3)  # Plot the wetbulb profile
    ax.annotate(str(int(round(thermo.ctof(prof.wetbulb[prof.sfc])))),
                xy=(prof.wetbulb[prof.sfc], prof.pres[prof.sfc] + 30),
                xytext=(prof.wetbulb[prof.sfc], prof.pres[prof.sfc] + 30),
                ha='left',
                color="c",
                family='sans-serif',
                weight='normal',
                zorder=7,
                fontsize=12,
                alpha=1.0)  # annotate the sfc wetbulb in F
    ax.semilogy(prof.dwpc,
                prof.pres,
                c=cb_colors.blue6,
                linestyle='-',
                lw=3,
                zorder=3)  # plot the dewpoint profile
    ax.annotate(str(int(round(thermo.ctof(prof.dwpc[prof.sfc])))),
                xy=(prof.dwpc[prof.sfc], prof.pres[prof.sfc] + 30),
                xytext=(prof.dwpc[prof.sfc], prof.pres[prof.sfc] + 30),
                ha='left',
                color=cb_colors.blue6,
                family='sans-serif',
                weight='bold',
                zorder=7,
                fontsize=12,
                alpha=1.0)  # annotate the sfc dewpoint in F
    ax.semilogy(prof.tmpc,
                prof.pres,
                c=cb_colors.orange6,
                linestyle='-',
                lw=3,
                zorder=3)  # Plot the temperature profile
    ax.semilogy(prof.vtmp,
                prof.pres,
                c=cb_colors.orange6,
                linestyle='--',
                lw=3,
                zorder=3)  # Plot the temperature profile
    ax.annotate(str(int(round(thermo.ctof(prof.tmpc[prof.sfc])))),
                xy=(prof.tmpc[prof.sfc], prof.pres[prof.sfc] + 30),
                xytext=(prof.tmpc[prof.sfc], prof.pres[prof.sfc] + 30),
                ha='left',
                color=cb_colors.orange6,
                family='sans-serif',
                weight='bold',
                zorder=7,
                fontsize=12,
                alpha=1.0)  # annotate the sfc temp in F
    ax.semilogy(pcl.ttrace,
                pcl.ptrace,
                c=cb_colors.gray6,
                linestyle='--',
                dashes=(3, 3),
                lw=1.5,
                alpha=1.0,
                zorder=3)  # plot the parcel trace

    #member_cape = []
    if members is not None:
        #   print( "Plotting members...")
        for m_idx in range(len(members['tmpc'])):
            ax.semilogy(members['dwpc'][m_idx],
                        members['pres'][m_idx],
                        c=cb_colors.blue6,
                        linestyle='-',
                        lw=1.,
                        zorder=1,
                        alpha=.6)  # plot the dewpoint profile
            ax.semilogy(members['tmpc'][m_idx],
                        members['pres'][m_idx],
                        c=cb_colors.orange6,
                        linestyle='-',
                        lw=1.,
                        zorder=1,
                        alpha=.6)  # Plot the temperature profile
# set label and tick marks for pressure and temperature
    ax.xaxis.set_major_locator(plt.MultipleLocator(10))
    ax.set_xticks(np.arange(-100, 60, 10))
    ax.set_xticklabels([str(i) for i in np.arange(-100, 60, 10)],
                       color=cb_colors.gray7,
                       fontsize=12)
    ax.set_xlim(-50, 50)
    ax.yaxis.set_major_formatter(plt.ScalarFormatter())
    ax.set_yticks(np.linspace(1000, 100, 19))
    ax.set_yticklabels(p_grid_labels, color=cb_colors.gray7, fontsize=12)
    ax.set_ylim(1050, 100)

    #plot the title text
    plt.text(0.05,
             0.97,
             title_text,
             fontsize=15,
             color=cb_colors.gray8,
             weight='bold',
             ha='left',
             transform=fig.transFigure)
    #x_hodo.annotate(sharptext, xy=(0.95, 0.95), xytext=(0.95, 0.95),xycoords='axes fraction',textcoords='axes fraction',ha='center', va='bottom', color=cb_colors.gray7, family='sans-serif', weight='bold', zorder=3,fontsize=14)
    plt.text(0.8,
             0.97,
             sharptext,
             fontsize=15,
             color=cb_colors.gray8,
             weight='bold',
             ha='left',
             transform=fig.transFigure)
    #adjust the skew-T plot to make room for the rest of the figures. This was important to make everything line up.
    plt.subplots_adjust(left=0.05, right=0.55, top=0.96, bottom=0.15)

    #Plot the height labels on the left axis
    ax2 = ax.twinx(
    )  #makes a twin of the skew-T subplot that's not skewed at 45 degrees
    plt.yscale('log', nonposy='clip')
    plt.yticks(p_interped, h_new_labels, color=cb_colors.green4, ha='left')
    ax2.yaxis.tick_left()
    ax2.tick_params(direction='in',
                    pad=-15,
                    axis='both',
                    which='major',
                    colors=cb_colors.green4,
                    length=10,
                    width=1.5)
    ax2.set_yticklabels(h_new_labels,
                        fontsize=12,
                        weight='bold',
                        color=cb_colors.green4)

    x = np.random.uniform(0.0, 10.0, 15)
    y = np.random.uniform(0.0, 10.0, 15)

    # Plot LCL and LFC levels
    plt.plot((38, 42), (pcl.lfcpres, pcl.lfcpres),
             c="darkgreen",
             lw=2.0,
             zorder=3)
    ax2.annotate('LFC',
                 xy=(40, pcl.lfcpres),
                 xytext=(40, pcl.lfcpres),
                 ha='center',
                 va='bottom',
                 color=cb_colors.green5,
                 family='sans-serif',
                 weight='bold',
                 zorder=3,
                 fontsize=12)
    plt.plot((38, 42), (pcl.lclpres, pcl.lclpres),
             c="r",
             linestyle='-',
             lw=2.0,
             zorder=3)
    ax2.annotate('LCL',
                 xy=(40, pcl.lclpres + 5.),
                 xytext=(40, pcl.lclpres + 5.),
                 ha='center',
                 va='top',
                 color=cb_colors.red5,
                 family='sans-serif',
                 weight='bold',
                 zorder=3,
                 fontsize=12)
    plt.plot((38, 42), (pcl.elpres, pcl.elpres),
             c="m",
             linestyle='-',
             lw=2.0,
             zorder=3)
    ax2.annotate('EL',
                 xy=(40, pcl.elpres),
                 xytext=(40, pcl.elpres),
                 ha='center',
                 va='bottom',
                 color=cb_colors.purple5,
                 family='sans-serif',
                 weight='bold',
                 zorder=3,
                 fontsize=12)

    # Plot Eff Inflow Layer
    eff_inflow = (prof.ebottom, prof.etop)
    eff_inflow_top = sharptab.interp.to_agl(
        prof, sharptab.interp.hght(prof, eff_inflow[1]))
    eff_inflow_bottom = sharptab.interp.to_agl(
        prof, sharptab.interp.hght(prof, eff_inflow[0]))
    bunkers = prof.srwind
    effective_srh = prof.right_esrh
    plt.plot((-25, -20), (eff_inflow[0], eff_inflow[0]),
             c=cb_colors.red5,
             linestyle='-',
             lw=1.75,
             zorder=3)
    plt.plot((-25, -20), (eff_inflow[1], eff_inflow[1]),
             c=cb_colors.red5,
             linestyle='-',
             lw=1.75,
             zorder=3)
    plt.plot((-22.5, -22.5), (eff_inflow[0], eff_inflow[1]),
             c=cb_colors.red5,
             linestyle='-',
             lw=1.75,
             zorder=3)
    try:
        plt.annotate(str(int(eff_inflow_bottom)) + 'm  ',
                     xy=(-25, eff_inflow[0]),
                     xytext=(-25, eff_inflow[0]),
                     ha='right',
                     va='center',
                     color=cb_colors.red5,
                     zorder=3,
                     fontsize=12,
                     weight='bold')
        plt.annotate(str(int(eff_inflow_top)) + 'm  ',
                     xy=(-25, eff_inflow[1]),
                     xytext=(-25, eff_inflow[1]),
                     ha='right',
                     va='center',
                     color=cb_colors.red5,
                     zorder=3,
                     fontsize=12,
                     weight='bold')
        plt.annotate(str(int(effective_srh[0])) + ' m$^2$/s$^2$',
                     xy=(-22.5, eff_inflow[1] - 10),
                     xytext=(-22.5, eff_inflow[1] - 10),
                     ha='center',
                     va='bottom',
                     color=cb_colors.red5,
                     zorder=3,
                     fontsize=12,
                     weight='bold')
    except:
        print("NO EFF INFLOW")

# PLOT WINDBARBS
    p_barb = np.asarray(p_barb)
    pidx = idx = np.where(np.asarray(p_barb) >= 100.)[0]
    wind_barbs = ax2.barbs(55 * np.ones(len(p_barb[idx])),
                           p_barb[idx],
                           u_barb[idx],
                           v_barb[idx],
                           barbcolor=cb_colors.gray7,
                           flagcolor='None',
                           zorder=10,
                           lw=1.0,
                           length=7)
    wind_barbs.set_clip_on(False)

    ax2.invert_yaxis()
    ax2.set_xlim(-50, 50)
    ax2.set_ylim(1050, 100)

    spd_barb = np.asarray(spd_barb)

    # Create hodograph ********************************************************************************************
    ax_hod = fig.add_axes([0.60, 0.45, 0.38, 0.475],
                          frameon=False)  #, facecolor='k')

    # Set the characteristics of the tick marks
    for tick in ax_hod.xaxis.get_major_ticks():
        tick.label.set_fontsize(12)
        tick.label.set_color(cb_colors.gray7)
        tick.label.set_weight('bold')
    for tick in ax_hod.yaxis.get_major_ticks():
        tick.label.set_fontsize(12)
        tick.label.set_color(cb_colors.gray7)
        tick.label.set_weight('bold')
    for i in range(10, 90, 10):

        # Draw the range rings around the hodograph.
        circle = plt.Circle((0, 0),
                            i,
                            linestyle='--',
                            color='k',
                            alpha=.3,
                            fill=False)
        ax_hod.add_artist(circle)

# Set the tick parameters to displace the tick labels from the hodograph axes
    ax_hod.tick_params(axis='x',
                       which='major',
                       labelsize=10,
                       color=cb_colors.gray7,
                       pad=-235,
                       length=0)
    ax_hod.tick_params(axis='y',
                       which='major',
                       labelsize=10,
                       color=cb_colors.gray7,
                       pad=-315,
                       length=0)

    # Plot the hodograph axes
    ax_hod.axvline(0, color=cb_colors.gray7, linestyle='-', linewidth=2.)
    ax_hod.axhline(0, color=cb_colors.gray7, linestyle='-', linewidth=2.)
    ax_hod.set_yticks(range(-60, 65, 10))
    ax_hod.set_xticks(range(-70, 75, 10))
    hod_yticklabels = [str(abs(i)) for i in range(-60, 65, 10)]
    #hod_yticklabels[len(hod_yticklabels)/2] = ''
    hod_xticklabels = [str(abs(i)) for i in range(-70, 75, 10)]
    #hod_xticklabels[len(hod_xticklabels)/2] = ''
    ax_hod.set_yticklabels(hod_yticklabels,
                           fontsize=12,
                           weight='bold',
                           color=cb_colors.gray7)
    ax_hod.set_xticklabels(hod_xticklabels,
                           fontsize=12,
                           weight='bold',
                           color=cb_colors.gray7)

    # Plot the hodograph using the color scheme for different layers (0-3, 3-6, etc.)
    bounds = [0, 1000, 3000, 6000, 9000, 12000]
    for i in range(1, len(bounds), 1):
        subset_idxs = np.where(
            (prof.hght <= sharptab.interp.to_msl(prof, bounds[i]))
            & (prof.hght >= sharptab.interp.to_msl(prof, bounds[i - 1])))
        subset_hghts = np.ma.concatenate(
            ([sharptab.interp.to_msl(prof, bounds[i - 1])],
             prof.hght[subset_idxs], [sharptab.interp.to_msl(prof,
                                                             bounds[i])]))
        u, v = sharptab.interp.components(
            prof, sharptab.interp.pres(prof, subset_hghts))
        ax_hod.plot(u,
                    v,
                    c=hodo_color[i - 1],
                    linewidth=2.5,
                    label=hodo_label[i - 1],
                    zorder=3)

    if members is not None:
        for mprof in members['member_profs']:
            for i in range(1, len(bounds), 1):
                subset_idxs = np.where(
                    (mprof.hght <= sharptab.interp.to_msl(mprof, bounds[i]))
                    & (mprof.hght >= sharptab.interp.to_msl(
                        mprof, bounds[i - 1])))
                subset_hghts = np.ma.concatenate(
                    ([sharptab.interp.to_msl(mprof, bounds[i - 1])
                      ], mprof.hght[subset_idxs],
                     [sharptab.interp.to_msl(mprof, bounds[i])]))
                u, v = sharptab.interp.components(
                    mprof, sharptab.interp.pres(mprof, subset_hghts))
                ax_hod.plot(u,
                            v,
                            c=hodo_color[i - 1],
                            linewidth=1.25,
                            alpha=0.6,
                            label=hodo_label[i - 1],
                            zorder=1)

# Get the Bunkers storm motions and convert them to strings to plot
    bunkers = srwind = prof.srwind
    bunkers_rt = utils.comp2vec(bunkers[0], bunkers[1])
    bunkers_lf = utils.comp2vec(bunkers[2], bunkers[3])
    bunkers_rt_str = str(int(np.ma.around(bunkers_rt[0], 0))) + "/" + str(
        int(np.ma.around(bunkers_rt[1], 0)))
    bunkers_lf_str = str(int(np.ma.around(bunkers_lf[0], 0))) + "/" + str(
        int(np.ma.around(bunkers_lf[1], 0)))

    # Plot the effective inflow layer on the hodograph
    effubot, effvbot = sharptab.interp.components(prof, eff_inflow[0])
    effutop, effvtop = sharptab.interp.components(prof, eff_inflow[1])
    ax_hod.plot([effubot, srwind[0]], [effvbot, srwind[1]],
                c='c',
                linewidth=1.5)
    ax_hod.plot([effutop, srwind[0]], [effvtop, srwind[1]],
                c='c',
                linewidth=1.5)

    # Annotate where the Bunkers storm motion vectors are on the hodograph
    ax_hod.plot(srwind[0],
                srwind[1],
                marker='o',
                fillstyle='none',
                markeredgecolor=cb_colors.blue8,
                markeredgewidth=1.5,
                markersize=11)
    ax_hod.annotate(bunkers_rt_str + ' RM', (srwind[0] + 1.5, srwind[1] - 1.5),
                    fontsize=12,
                    va="top",
                    ha="left",
                    color='k',
                    weight='bold',
                    zorder=10)
    ax_hod.plot(srwind[2],
                srwind[3],
                marker='o',
                fillstyle='none',
                markeredgecolor=cb_colors.blue8,
                markeredgewidth=1.5,
                markersize=11)
    ax_hod.annotate(bunkers_lf_str + ' LM', (srwind[2] + 1.5, srwind[3] - 1.5),
                    fontsize=12,
                    va="top",
                    ha="left",
                    color='k',
                    weight='bold',
                    zorder=10)

    # Annotate where the Corfidi MBE vectors are on the hodograph
    corfidi = prof.upshear_downshear
    corfidi_up = utils.comp2vec(corfidi[0], corfidi[1])
    corfidi_dn = utils.comp2vec(corfidi[2], corfidi[3])
    c = 'k'  #'#0A74C6'
    ax_hod.plot(corfidi[0],
                corfidi[1],
                marker='o',
                fillstyle='none',
                markeredgecolor=c,
                markeredgewidth=1.5,
                markersize=9)
    ax_hod.annotate(str(int(corfidi_up[0])) + '/' + str(int(corfidi_up[1])) +
                    ' UP', (corfidi[0] + 1.5, corfidi[1] - 1.5),
                    fontsize=12,
                    va="top",
                    ha="left",
                    color=cb_colors.purple8,
                    weight='bold',
                    zorder=10)
    ax_hod.plot(corfidi[2],
                corfidi[3],
                marker='o',
                fillstyle='none',
                markeredgecolor=c,
                markeredgewidth=1.5,
                markersize=9)
    ax_hod.annotate(str(int(corfidi_dn[0])) + '/' + str(int(corfidi_dn[1])) +
                    ' DN', (corfidi[2] + 1.5, corfidi[3] - 1.5),
                    fontsize=12,
                    va="top",
                    ha="left",
                    color=cb_colors.purple8,
                    weight='bold',
                    zorder=10)

    # Get the cloud-layer mean wind
    mean_cloudlayer = winds.mean_wind(prof, pbot=pcl.lclpres, ptop=pcl.elpres)
    mean_cloudlayer_comp = utils.comp2vec(mean_cloudlayer[0],
                                          mean_cloudlayer[1])
    try:
        mean_cloudlayer_str = str(int(np.ma.around(
            mean_cloudlayer_comp[0], 0))) + "/" + str(
                int(np.ma.around(mean_cloudlayer_comp[1], 0)))
    except:
        mean_cloudlayer_str = 'M/M'

# Write the critical angle to the hodograph.
    if eff_inflow[0] == prof.pres[prof.sfc]:
        ax_hod.annotate('Critical Angle = ' + str(int(prof.critical_angle)),
                        (-65, -50),
                        fontsize=12,
                        va="bottom",
                        ha="left",
                        color=cb_colors.green6,
                        weight='bold',
                        zorder=10)

    ax_hod.set_xlim(-80, 80)
    ax_hod.set_ylim(-70, 70)

    #BELOW IS STUFF FOR BOXES/BORDERS ******************************************************************************

    ax3 = ax2.twinx()
    ax3.axes.get_xaxis().set_visible(False)
    ax3.axes.get_yaxis().set_visible(False)
    ax3.set_yticks([])
    ax3.set_yticklabels([])

    #Big Thick Box around Skew-T
    #box = ax3.add_patch(patches.Rectangle((-50, 0), 110.0, 1.0,fill=False,linewidth=2,edgecolor="w",zorder=3))
    #box.set_clip_on(False)

    #box around hodograph
    #box = ax_hod.add_patch(patches.Rectangle((-80., -70.), 160., 140.,fill=False,linewidth=2,edgecolor="w",zorder=4))
    #box.set_clip_on(False)

    inset_color = cb_colors.gray7

    #THICK TEXT BOX around Thermodynamics Text
    box = ax3.add_patch(
        patches.Rectangle((-58.0, -0.035),
                          54,
                          -0.12,
                          fill=False,
                          linewidth=2,
                          edgecolor=inset_color,
                          zorder=4))
    box.set_clip_on(False)

    #THICK TEXT BOX around Kinematics Text
    box = ax3.add_patch(
        patches.Rectangle((-3.0, -0.035),
                          60,
                          -0.12,
                          fill=False,
                          linewidth=2,
                          edgecolor=inset_color,
                          zorder=4))
    box.set_clip_on(False)

    #THICK TEXT BOX Around Dynamics Text
    #   box = ax3.add_patch(patches.Rectangle((9.0, -0.04), 60, -0.38,fill=False,linewidth=2,edgecolor=inset_color,zorder=4))
    #   box.set_clip_on(False)

    #THICK TEXT BOX Around SARS Text
    #   box = ax3.add_patch(patches.Rectangle((69.0, -0.04), 55, -0.38,fill=False,linewidth=2,edgecolor=inset_color,zorder=4))
    #   box.set_clip_on(False)

    #Thermodynamics
    #box = ax3.add_patch(patches.Rectangle((-55.0, -0.04), 64.0, -0.12,fill=False,linewidth=1,edgecolor=inset_color,zorder=4))
    #box.set_clip_on(False)
    #box = ax3.add_patch(patches.Rectangle((-55.0, -0.04), 64.0, -0.025,fill=False,linewidth=1,edgecolor=inset_color,zorder=4))
    #box.set_clip_on(False)

    # Write the parcel properties to the inset.
    #x_list = [0, 0.08, 0.17, 0.25, 0.33, 0.39, 0.47]
    x_list = np.array([0, 0.08, 0.17, 0.25, 0.33, 0.39, 0.47]) - 0.075
    y_list = [-0.045, -0.07, -0.0925, -0.115, -0.1375]
    A = [
        "SFC", prof.sfcpcl.bplus,
        int(prof.sfcpcl.bminus), prof.sfcpcl.lclhght, prof.sfcpcl.li5,
        prof.sfcpcl.lfchght, prof.sfcpcl.elhght
    ]
    #   B = ["FCST", prof.fcstpcl.bplus, int(prof.fcstpcl.bminus), prof.fcstpcl.lclhght, prof.fcstpcl.li5, prof.fcstpcl.lfchght, prof.fcstpcl.elhght]
    C = [
        "ML", prof.mlpcl.bplus,
        int(prof.mlpcl.bminus), prof.mlpcl.lclhght, prof.mlpcl.li5,
        prof.mlpcl.lfchght, prof.mlpcl.elhght
    ]
    D = [
        "MU", prof.mupcl.bplus,
        int(prof.mupcl.bminus), prof.mupcl.lclhght, prof.mupcl.li5,
        prof.mupcl.lfchght, prof.mupcl.elhght
    ]
    #mlcape = C[1]
    #print('mlcape',mlcape)
    data = np.array([["PCL", "CAPE", "CINH", "LCL", "LI", "LFC", "EL"],
                     [
                         str(int(np.ma.around(A[i], 0))) if
                         (type(A[i]) == np.float64) else str(A[i])
                         for i in range(len(A))
                     ],
                     [
                         str(int(np.ma.around(C[i], 0))) if
                         (type(C[i]) == np.float64) else str(C[i])
                         for i in range(len(C))
                     ],
                     [
                         str(int(np.ma.around(D[i], 0))) if
                         (type(D[i]) == np.float64) else str(D[i])
                         for i in range(len(D))
                     ]])

    for i in range(data.shape[0]):
        for j in range(data.shape[1]):
            ax2.annotate(data[i, j], (x_list[j], y_list[i]),
                         xycoords="axes fraction",
                         fontsize=12,
                         va="top",
                         ha="left",
                         color=cb_colors.gray7,
                         weight='bold')

# Draw a box around the selected parcel being shown in the Skew-T
    box = ax3.add_patch(
        patches.Rectangle((-57.7, pcl_box_level),
                          53.,
                          0.0225,
                          fill=False,
                          linewidth=1,
                          edgecolor=cb_colors.purple4,
                          zorder=4))
    box.set_clip_on(False)

    # Write the lapse rates to the inset.
    #box = ax3.add_patch(patches.Rectangle((-55.0, -0.305), 43.0, -0.115,fill=False,linewidth=1,edgecolor="w",zorder=4))
    #box.set_clip_on(False)
    x_list = [0.15, 0.16]
    y_list = np.arange(-0.315, -.40, -0.0225)
    data = np.array([[
        "0-3km AGL LR =",
        str(np.ma.around(prof.lapserate_3km, 1)) + " C/km"
    ], [
        "3-6km AGL LR =",
        str(np.ma.around(prof.lapserate_3_6km, 1)) + " C/km"
    ],
                     [
                         "850-500mb LR =",
                         str(np.ma.around(prof.lapserate_850_500, 1)) + " C/km"
                     ],
                     [
                         "700-500mb LR =",
                         str(np.ma.around(prof.lapserate_700_500, 1)) + " C/km"
                     ]])
    for i in range(data.shape[0]):
        for j in range(data.shape[1]):
            if (j % 2 == 0):
                ax2.annotate(data[i, j], (x_list[j], y_list[i]),
                             xycoords="axes fraction",
                             fontsize=12,
                             va="top",
                             ha="right",
                             color='k',
                             weight='bold')
            else:
                ax2.annotate(data[i, j], (x_list[j], y_list[i]),
                             xycoords="axes fraction",
                             fontsize=12,
                             va="top",
                             ha="left",
                             color='k',
                             weight='bold')

#Severe Indices
#box = ax3.add_patch(patches.Rectangle((-12.0, -0.305), 21.0, -0.115,fill=False,linewidth=1,edgecolor="w",zorder=4))
#box.set_clip_on(False)
    x_list = [0.52, 0.53]
    y_list = np.arange(-0.315, -.40, -0.0225)

    # This looks lifted from the Profile class.  Don't need this.
    sfc = prof.pres[prof.sfc]
    p6km = sharptab.interp.pres(prof, sharptab.interp.to_msl(prof, 6000.))
    p8km = sharptab.interp.pres(prof, sharptab.interp.to_msl(prof, 8000.))
    #   ebot_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[0]))
    #   etop_hght = interp.to_agl(prof, interp.hght(prof, eff_inflow[1]))

    # Mean winds
    #mean_1km = winds.mean_wind(prof, pbot=sfc, ptop=p1km)
    mean_1km_comp = prof.mean_1km  #utils.comp2vec(mean_1km[0],mean_1km[1])
    #mean_3km = winds.mean_wind(prof, pbot=sfc, ptop=p3km)
    mean_3km_comp = prof.mean_3km  #utils.comp2vec(mean_3km[0],mean_3km[1])
    #mean_eff = winds.mean_wind(prof, pbot=eff_inflow[0], ptop=eff_inflow[1])
    mean_eff_comp = utils.comp2vec(
        *prof.mean_eff)  #utils.comp2vec(mean_eff[0],mean_eff[1])

    if type(eff_inflow[0]) != np.float64:
        mean_eff_comp = ['---', '--']
    mean_6km = winds.mean_wind(prof, pbot=sfc, ptop=p6km)
    mean_6km_comp = prof.mean_6km  #utils.comp2vec(mean_6km[0],mean_6km[1])
    mean_8km = winds.mean_wind(prof, pbot=sfc, ptop=p8km)
    mean_8km_comp = prof.mean_8km  #utils.comp2vec(mean_8km[0],mean_8km[1])
    mean_cloudlayer = winds.mean_wind(prof, pbot=pcl.lclpres, ptop=pcl.elpres)
    mean_cloudlayer_comp = prof.mean_lcl_el  #utils.comp2vec(mean_cloudlayer[0],mean_cloudlayer[1])
    mean_ebwd = winds.mean_wind(prof, pbot=eff_inflow[0], ptop=eff_inflow[1])
    mean_ebwd_comp = utils.comp2vec(
        *prof.mean_ebw)  #utils.comp2vec(mean_ebwd[0],mean_ebwd[1])

    if type(eff_inflow[0]) != np.float64:
        mean_ebwd_comp = ['---', '--']

    bunkers_rt = utils.comp2vec(bunkers[0], bunkers[1])
    bunkers_lf = utils.comp2vec(bunkers[2], bunkers[3])
    corfidi_up = utils.comp2vec(corfidi[0], corfidi[1])
    corfidi_dn = utils.comp2vec(corfidi[2], corfidi[3])
    srw_1km = prof.srw_1km  #utils.comp2vec(*winds.sr_wind(prof, pbot=sfc, ptop=p1km, stu=prof.srwind[0], stv=prof.srwind[1]))
    srw_3km = prof.srw_3km  #utils.comp2vec(*winds.sr_wind(prof, pbot=sfc, ptop=p3km, stu=prof.srwind[0], stv=prof.srwind[1]))
    srw_eff = utils.comp2vec(
        *prof.srw_eff
    )  #utils.comp2vec(*winds.sr_wind(prof, pbot=eff_inflow[0], ptop=eff_inflow[1], stu=prof.srwind[0], stv=prof.srwind[1]))
    if type(eff_inflow[0]) != np.float64:
        srw_eff = ['---', '--']
    srw_6km = prof.srw_6km  #utils.comp2vec(*winds.sr_wind(prof, pbot=sfc, ptop=p6km, stu=prof.srwind[0], stv=prof.srwind[1]))
    srw_8km = prof.srw_8km  #utils.comp2vec(*winds.sr_wind(prof, pbot=sfc, ptop=p8km, stu=prof.srwind[0], stv=prof.srwind[1]))
    srw_cloudlayer = prof.srw_lcl_el  #utils.comp2vec(*winds.sr_wind(prof, pbot=pcl.lclpres, ptop=pcl.elpres, stu=prof.srwind[0], stv=prof.srwind[1]))
    srw_ebwd = utils.comp2vec(
        *prof.srw_ebw
    )  #utils.comp2vec(*winds.sr_wind(prof, pbot=eff_inflow[0], ptop=eff_inflow[1], stu=prof.srwind[0], stv=prof.srwind[1]))
    if type(eff_inflow[0]) != np.float64:
        srw_ebwd = ['---', '--']
    srw_46km = utils.comp2vec(
        *prof.srw_4_6km
    )  #utils.comp2vec(*winds.sr_wind(prof, pbot=p4km, ptop=p6km, stu=prof.srwind[0], stv=prof.srwind[1]))
    sfc_8km_shear = prof.sfc_8km_shear  #winds.wind_shear(prof, pbot=sfc, ptop=p8km)
    sfc_6km_shear = prof.sfc_6km_shear  #winds.wind_shear(prof, pbot=sfc, ptop=p6km)
    sfc_3km_shear = prof.sfc_3km_shear  #winds.wind_shear(prof, pbot=sfc, ptop=p3km)
    sfc_1km_shear = prof.sfc_1km_shear  #winds.wind_shear(prof, pbot=sfc, ptop=p1km)
    effective_shear = prof.eff_shear  #winds.wind_shear(prof, pbot=eff_inflow[0], ptop=etop_hght)
    cloudlayer_shear = prof.lcl_el_shear  #winds.wind_shear(prof,pbot= pcl.lclpres, ptop=pcl.elpres)
    srh3km = prof.srh3km  #winds.helicity(prof, 0, 3000., stu = bunkers[0], stv = bunkers[1])
    srh1km = prof.srh1km  #winds.helicity(prof, 0, 1000., stu = bunkers[0], stv = bunkers[1])
    stp_fixed = prof.stp_fixed  #params.stp_fixed(pcl.bplus, pcl.lclhght, srh1km[0], utils.comp2vec(sfc_6km_shear[0], sfc_6km_shear[1])[1])
    ship = prof.ship
    effective_srh = prof.right_esrh  #winds.helicity(prof, ebot_hght, etop_hght, stu = bunkers[0], stv = bunkers[1])
    ebwd = prof.ebwd  #winds.wind_shear(prof, pbot=eff_inflow[0], ptop=eff_inflow[1])
    ebwspd = prof.ebwspd
    scp = prof.right_scp
    stp_cin = prof.stp_cin  #params.stp_cin(pcl.bplus, effective_srh[0], ebwspd, pcl.lclhght, pcl.bminus)
    brn_shear = pcl.brnshear

    # Draw the SCP, STP, SHIP indices to the plot
    # TODO: Include the color variations on this to denote intensity of the index.

    #   if prof.stp_fixed is ma.masked:
    #      temp_stp_fixed = '0.0'
    #   else:
    #      temp_stp_fixed = str(round(prof.stp_fixed,1))

    #   if prof.stp_cin is ma.masked:
    #      temp_stp_cin = '0.0'
    #   else:
    #      temp_stp_cin = str(round(prof.stp_cin,1))

    #   if prof.right_scp is ma.masked:
    #      temp_right_scp = '0.0'
    #   else:
    #      temp_right_scp = str(round(prof.right_scp,1))

    #   data = np.array([["Supercell =",temp_right_scp],
    #                       ["STP (cin) =",temp_stp_cin],
    #                       ["STP (fix) =",temp_stp_fixed]])

    data = np.array([["Supercell =",
                      str(np.ma.around(prof.right_scp, 1))],
                     ["STP (cin) =",
                      str(np.ma.around(prof.stp_cin, 1))],
                     ["STP (fix) =",
                      str(np.ma.around(prof.stp_fixed, 1))]])

    data = np.array([["Supercell =",
                      str(np.ma.around(prof.right_scp, 1))],
                     ["STP (cin) =",
                      str(np.ma.around(prof.stp_cin, 1))],
                     ["STP (fix) =",
                      str(np.ma.around(prof.stp_fixed, 1))],
                     ["SHIP =", str(np.ma.around(prof.ship, 1))]])
    '''
   for i in range(data.shape[0]):
      for j in range(data.shape[1]):
         d = float(data[i,1])
         if i == 0:
            if d >= 19.95:
               c = MAGENTA
            elif d >= 11.95:
               c = RED
            elif d >= 1.95:
               c = YELLOW
            elif d >= .45:
               c = WHITE
            elif d >= -.45:
               c = LBROWN
            elif d < -0.45:
               c = CYAN
         elif i == 1:
            if d >= 8:
               c = MAGENTA
            elif d >= 4:
               c = RED
            elif d >= 2:
               c = YELLOW
            elif d >= 1:
               c = WHITE
            elif d >= .5:
               c = LBROWN
            elif d < .5:
               c = DBROWN
               stpCinColor = c
         elif i == 2:
            if d >= 7:
               c = MAGENTA
            elif d >= 5:
               c = RED
            elif d >= 2:
               c = YELLOW
            elif d >= 1:
               c = WHITE
            elif d >= 0.5:
               c = LBROWN
            else:
               c = DBROWN
         elif i == 3:
            if d >= 5:
               c = MAGENTA
            elif d >= 2:
               c = RED
            elif d >= 1:
               c = YELLOW
            elif d >= .5:
               c = WHITE
            else:
               c = DBROWN
         if (j % 2 == 0):
            ax2.annotate(data[i,j], (x_list[j], y_list[i]), xycoords="axes fraction",
                         fontsize=12, va="top", ha="right", color=c, weight='bold')
         else:
            ax2.annotate(data[i,j], (x_list[j], y_list[i]), xycoords="axes fraction",
                       fontsize=12, va="top", ha="left", color=cb_colors.gray7, weight='bold')
   '''
    # Draw the kinematic inset on the plot
    #   box = ax3.add_patch(patches.Rectangle((9.0, -0.04), 60.0, -0.025,fill=False,linewidth=1,edgecolor="w",zorder=4))
    #   box.set_clip_on(False)
    x_list = np.array([0.60, 0.84, 0.97, 1.08, 1.18]) - 0.12
    y_list = [-0.045]
    y_list.extend(np.arange(-.07, -0.12, -.0225).tolist())
    y_list.extend(np.arange(-.145, -0.22, -.0225).tolist())
    y_list.extend(np.arange(-.2425, -0.27, -.0225).tolist())
    y_list.extend(np.arange(-0.295, -.4, -0.0225).tolist())

    A = [
        "SFC-1km", srh1km[0],
        utils.comp2vec(sfc_1km_shear[0], sfc_1km_shear[1])[1]
    ]
    A2 = [mean_1km_comp, srw_1km]
    B = [
        "SFC-3km", srh3km[0],
        utils.comp2vec(sfc_3km_shear[0], sfc_3km_shear[1])[1]
    ]
    B2 = [mean_3km_comp, srw_3km]
    C = [
        "Eff Inflow Layer", effective_srh[0],
        utils.comp2vec(effective_shear[0], effective_shear[1])[1]
    ]
    C2 = [mean_eff_comp, srw_eff]
    #   D = ["SFC-6km", "", utils.comp2vec(sfc_6km_shear[0],sfc_6km_shear[1])[1]]
    #   D2 = [mean_6km_comp, srw_6km]
    #   E = ["SFC-8km", "", utils.comp2vec(sfc_8km_shear[0],sfc_8km_shear[1])[1]]
    #   E2 = [mean_8km_comp, srw_8km]
    #   F = ["LCL-EL (CLoud Layer)", "", utils.comp2vec(cloudlayer_shear[0],cloudlayer_shear[1])[1]]
    #   F2 = [mean_cloudlayer_comp, srw_cloudlayer]
    #   G = ["Eff Shear (EBWD)", "", utils.comp2vec(ebwd[0],ebwd[1])[1]]
    #   G2 = [mean_ebwd_comp, srw_ebwd]
    #   H = ["BRN Shear (m2/s2)", "", brn_shear, "", ""]
    #   I = ["4-6km SR Wind", ""]
    #   I2 = [str(int(round(srw_46km[0],0)))+"/"+str(int(round(srw_46km[1],0)))]
    #   I3 = ["", ""]
    #   J = ["...Storm Motion Vectors...", "", "", "", ""]
    #   K = ["Bunkers Right", ""]
    #   K2 = [str(int(round(bunkers_rt[0],0)))+"/"+str(int(round(bunkers_rt[1],0)))]
    #   K3 = ["", ""]
    #   L = ["Bunkers Left", ""]
    #   L2 = [str(int(round(bunkers_lf[0],0)))+"/"+str(int(round(bunkers_lf[1],0)))]
    #   L3 = ["", ""]
    #   M = ["Corfidi Downshear", ""]
    #   M2 = [str(int(round(corfidi_dn[0],0)))+"/"+str(int(round(corfidi_dn[1],0)))]
    #   M3 = ["", ""]
    #   N = ["Corfidi Upshear", ""]
    #   N2 = [str(int(round(corfidi_up[0],0)))+"/"+str(int(round(corfidi_up[1],0)))]
    #   N3 = ["", ""]

    data = np.array([np.array(["", "SRH (m2/s2)", "Shear (kt)", "MnWind", "SRW"]),
                     np.array([ str(int(round(A[i],0))) if (type(A[i])== np.float64) else str(A[i]) for i in range(len(A)) ]+\
                        [ str(int(np.ma.around(A2[i][0],0)))+"/"+str(int(np.ma.around(A2[i][1],0))) if (type(A2[i][0])== np.ma.core.MaskedArray) else str(A2[i][0])+"/"+str(A2[i][1]) for i in range(len(A2)) ]),

                     np.array([ str(int(round(B[i],0))) if (type(B[i])== np.float64) else str(B[i]) for i in range(len(B)) ]+\
                         [ str(int(np.ma.around(B2[i][0],0)))+"/"+str(int(np.ma.around(B2[i][1],0))) if (type(B2[i][0])== np.ma.core.MaskedArray) else str(B2[i][0])+"/"+str(B2[i][1]) for i in range(len(B2)) ]),

                     np.array([ str(int(np.ma.around(C[i],0))) if (type(C[i])== np.float64) else str(C[i]) for i in range(len(C)) ]+\
                         [ str(int(np.ma.around(C2[i][0],0)))+"/"+str(int(np.ma.around(C2[i][1],0))) if (type(C2[i][0])== np.ma.core.MaskedArray) else str(C2[i][0])+"/"+str(C2[i][1]) for i in range(len(C2)) ])]) #,

    #                    np.array([ str(int(round(D[i],0))) if (type(D[i])== np.float64) else str(D[i]) for i in range(len(D)) ]+\
    #                        [ str(int(round(D2[i][0],0)))+"/"+str(int(round(D2[i][1],0))) if (type(D2[i][0])== np.ma.core.MaskedArray) else str(D2[i][0])+"/"+str(D2[i][1]) for i in range(len(D2)) ]),

    #                    np.array([ str(int(round(E[i],0))) if (type(E[i])== np.float64) else str(E[i]) for i in range(len(E)) ]+\
    #                        [ str(int(round(E2[i][0],0)))+"/"+str(int(round(E2[i][1],0))) if (type(E2[i][0])== np.ma.core.MaskedArray) else str(E2[i][0])+"/"+str(E2[i][1]) for i in range(len(E2)) ]),

    #                    np.array([ str(int(round(F[i],0))) if (type(F[i])== np.float64) else str(F[i]) for i in range(len(F)) ]+\
    #                        [ str(int(round(F2[i][0],0)))+"/"+str(int(round(F2[i][1],0))) if (type(F2[i][0])== np.ma.core.MaskedArray) else str(F2[i][0])+"/"+str(F2[i][1]) for i in range(len(F2)) ]),

    #                    np.array([ str(int(round(G[i],0))) if (type(G[i])== np.float64) else str(G[i]) for i in range(len(G)) ]+\
    #                        [ str(int(round(G2[i][0],0)))+"/"+str(int(round(G2[i][1],0))) if (type(G2[i][0])== np.ma.core.MaskedArray) else str(G2[i][0])+"/"+str(G2[i][1]) for i in range(len(G2)) ]),

    #                    np.array([ str(int(round(H[i],0))) if (type(H[i])== np.float64) else str(H[i]) for i in range(len(H)) ]),
    #                    np.array(I+I2+I3),
    #                    np.array(J),
    #                    np.array(K+K2+K3),
    #                    np.array(L+L2+L3),
    #                    np.array(M+M2+M3),
    #                    np.array(N+N2+N3)])
    #x_list = np.array([0, 0.08, 0.17, 0.25, 0.33, 0.39, 0.47])-0.05
    y_list = [-0.045, -0.07, -0.0925, -0.115, -0.1375]
    for i in range(data.shape[0]):
        for j in range(data[0].shape[0]):
            if j > 0:
                ax2.annotate(data[i][j], (x_list[j], y_list[i]),
                             xycoords="axes fraction",
                             fontsize=12,
                             va="top",
                             ha="right",
                             color=cb_colors.gray7,
                             weight='bold')
            else:
                ax2.annotate(data[i][j], (x_list[j], y_list[i]),
                             xycoords="axes fraction",
                             fontsize=12,
                             va="top",
                             ha="left",
                             color=cb_colors.gray7,
                             weight='bold')


#    wind_1km = utils.vec2comp(prof.wind1km[0], prof.wind1km[1])
#    wind_6km = utils.vec2comp(prof.wind6km[0], prof.wind6km[1])
#    wind_barbs = ax2.barbs(58, 2200, wind_1km[0], wind_1km[1], color='#AA0000', zorder=3, lw=1.25,length=9)
#    wind_barbs.set_clip_on(False)
#    wind_barbs = ax2.barbs(58, 2200, wind_6km[0], wind_6km[1], color='#0A74C6', zorder=3, lw=1.25,length=9)
#    wind_barbs.set_clip_on(False)
#    ax2.annotate("1km & 6km AGL\nWind Barbs", (1.08,-0.37), xycoords="axes fraction", fontsize=12, va="top", ha="center", color='#0A74C6', weight='bold')

# Draw the CAPE vs. SRH Scatter
#ax_EFSTP = fig.add_axes([0.74625, 0.0229, 0.20375, 0.2507], frameon=False)
#x_EFSTP = fig.add_axes([0.72625, 0.0229, 0.20375, 0.2507], frameon=False)
    ax_EFSTP = fig.add_axes([0.625, 0.05, 0.35, 0.3], frameon=False)

    for member_no, c in zip(
            np.arange(1, 19, 1),
            np.tile([
                cb_colors.orange6, cb_colors.orange6, cb_colors.green6,
                cb_colors.green6, cb_colors.purple6, cb_colors.purple6
            ], (3, 1))):
        memidx = [0, 10, 11, 12, 13, 14, 15, 16, 17, 1, 2, 3, 4, 5, 6, 7, 8, 9]
        ax_EFSTP.scatter(xpts[memidx[member_no - 1], :, :].ravel(),
                         ypts[memidx[member_no - 1], :, :].ravel(),
                         color=c,
                         marker='o',
                         s=5,
                         alpha=0.7)
    ax_EFSTP.set_xticks(np.arange(0, 5001, 1000))
    ax_EFSTP.set_yticks(np.arange(0, 601, 100))
    #ax_EFSTP.set_xticklabels(np.arange(0,5001,1000),color='k',fontsize=12)
    #ax_EFSTP.set_yticklabels(np.arange(0,601,100),color='k',fontsize=12)
    ax_EFSTP.set_xlabel('MLCAPE', weight='bold', fontsize=14)
    ax_EFSTP.set_ylabel('0-1km SRH', weight='bold', fontsize=14)
    ax_EFSTP.tick_params(axis='both', labelsize=12, labelcolor='k')
    ax_EFSTP.set_xlim(-200, 5000)
    ax_EFSTP.set_ylim(-100, 600)
    #ax_EFSTP.tick_params(direction='in', axis='x', which='major', colors=cb_colors.gray4,length=0,width=1.5,size=12)#pad=-10
    #ax_EFSTP.tick_params(direction='in', axis='y', which='major', colors=cb_colors.gray4,length=0,width=1.5,size=12)#pad=-23
    ax_EFSTP.grid(color=cb_colors.gray4,
                  linestyle='--',
                  dashes=(3, 3),
                  alpha=0.75,
                  zorder=0,
                  linewidth=1.25)
    ax_EFSTP.text(0.8,
                  0.95,
                  'YSU',
                  color=cb_colors.orange6,
                  transform=ax_EFSTP.transAxes,
                  fontsize=16,
                  weight='bold')
    ax_EFSTP.text(0.8,
                  0.89,
                  'MYJ',
                  color=cb_colors.green6,
                  transform=ax_EFSTP.transAxes,
                  fontsize=16,
                  weight='bold')
    ax_EFSTP.text(0.8,
                  0.83,
                  'MYNN',
                  color=cb_colors.purple6,
                  transform=ax_EFSTP.transAxes,
                  fontsize=16,
                  weight='bold')
    box = ax_EFSTP.add_patch(
        patches.Rectangle((0, -1),
                          13,
                          13,
                          fill=False,
                          linewidth=2,
                          edgecolor=cb_colors.gray4,
                          zorder=10))
    box.set_clip_on(False)

    ax_EFSTP.annotate("0-1 km SRH vs. 100-mb MLCAPE", (0.5, 1.075),
                      xycoords="axes fraction",
                      fontsize=14,
                      va="center",
                      ha="center",
                      color=cb_colors.gray7,
                      weight='bold')
    ax_EFSTP.annotate("(9 km neighborhood)", (0.5, 1.025),
                      xycoords="axes fraction",
                      fontsize=12,
                      va="center",
                      ha="center",
                      color=cb_colors.gray7,
                      weight='bold')

    plt.savefig(figname, facecolor=fig.get_facecolor())  #, edgecolor=None)
コード例 #5
0
ファイル: params.py プロジェクト: metpy/SHARPpy
def unstable_level(prof, lower, upper):
    '''
    Finds the most unstable level between the lower and upper levels.

    Inputs
    ------
        prof        (profile object)    Profile Object
        lower       (float)             Bottom level (hPa) [-1=SFC]
        upper       (float)             Top level (hPa) [-1=SFC-100hPa]

    Returns
    -------
        Pressure Level of most unstable level   (float [hPa])
    '''
    if lower == -1: lower = prof.gSndg[prof.sfc][prof.pind]
    if upper == -1: upper = prof.gSndg[prof.sfc][prof.pind] - 400.

    # Make sure this is a valid layer
    while not QC(interp.dwpt(upper, prof)):
        upper += 50.
    if not QC(interp.temp(lower, prof)): lower = prof.gSndg[prof.sfc][0]

    # Find lowest observations in the layer
    i = 0
    while prof.gSndg[i][prof.pind] > lower:
        i += 1
    while not QC(prof.gSndg[i][prof.tind]):
        i += 1
    lptr = i
    if prof.gSndg[i][prof.pind] == lower: lptr += 1

    # Find highest observations in the layer
    i = prof.gNumLevels - 1
    while prof.gSndg[i][prof.pind] < upper:
        i -= 1
    uptr = i
    if prof.gSndg[i][prof.pind] == upper: uptr -= 1

    # Start with interpolated bottom layer
    p1 = lower
    t1 = interp.temp(p1, prof)
    td1 = interp.dwpt(p1, prof)
    p2, t2 = thermo.drylift(p1, t1, td1)
    tmax = thermo.wetlift(p2, t2, 1000.)
    pmax = p1

    # Calculate every level that reports a dew point
    for i in range(lptr, uptr + 1):
        if QC(prof.gSndg[i][prof.tdind]):
            p1 = prof.gSndg[i][prof.pind]
            t1 = prof.gSndg[i][prof.tind]
            td1 = prof.gSndg[i][prof.tdind]
            p2, t2 = thermo.drylift(p1, t1, td1)
            t1 = thermo.wetlift(p2, t2, 1000.)
            if t1 > tmax:
                tmax = t1
                pmax = p1

    # Finish with interpolated top layer
    p1 = upper
    t1 = interp.temp(p1, prof)
    td1 = interp.dwpt(p1, prof)
    p2, t2 = thermo.drylift(p1, t1, td1)
    t1 = thermo.wetlift(p2, t2, 1000.)
    if t1 > tmax:
        pmax = prof.gSndg[i][prof.pind]

    return pmax
コード例 #6
0
ファイル: params.py プロジェクト: metpy/SHARPpy
def parcelx(lower, upper, pres, temp, dwpt, prof, **kwargs):
    '''
    Lifts the specified parcel, calculated various levels and parameters from
    the profile object. B+/B- are calculated based on the specified layer.

    !! All calculations use the virtual temperature correction unless noted. !!

    Inputs
    ------
        lower       (float)                 Lower-bound lifting level (hPa)
        upper       (float)                 Upper-bound lifting level
        pres        (float)                 Pressure of parcel to lift (hPa)
        temp        (float)                 Temperature of parcel to lift (C)
        dwpt        (float)                 Dew Point of parcel to lift (C)
        prof        (profile object)        Profile Object

    Returns
    -------
        pcl         (parcel object)         Parcel Object
    '''
    pcl = Parcel(-1, -1, pres, temp, dwpt)
    if 'lplvals' in kwargs: pcl.lplvals = kwargs.get('lplvals')
    else:
        lplvals = DefineParcel(prof, 5, pres=pres, temp=temp, dwpt=dwpt)
        pcl.lplvals = lplvals

    if prof.gNumLevels < 1: return pcl

    lyre = -1
    cap_strength = RMISSD
    cap_strengthpres = RMISSD
    li_max = RMISSD
    li_maxpres = RMISSD
    totp = 0.
    totn = 0.
    tote = 0.
    cinh_old = 0.

    # See if default layer is specified
    if lower == -1:
        lower = prof.gSndg[prof.sfc][prof.pind]
        pcl.blayer = lower
    if upper == -1:
        upper = prof.gSndg[prof.gNumLevels - 1][prof.pind]
        pcl.tlayer = upper

    # Make sure that this is a valid layer
    if lower > pres:
        lower = pres
        pcl.blayer = lower
    if not QC(interp.vtmp(lower, prof)) or \
       not QC(interp.vtmp(upper, prof)):
        return RMISSD

    # Begin with the Mixing Layer
    te1 = interp.vtmp(pres, prof)
    pe1 = lower
    h1 = interp.hght(pe1, prof)
    tp1 = thermo.virtemp(pres, temp, dwpt)
    # te1 = tp1

    # Lift parcel and return LCL pres (hPa) and LCL temp (c)
    pe2, tp2 = thermo.drylift(pres, temp, dwpt)
    blupper = pe2  # Define top of layer as LCL pres
    h2 = interp.hght(pe2, prof)
    te2 = interp.vtmp(pe2, prof)
    pcl.lclpres = pe2
    pcl.lclhght = interp.agl(h2, prof)

    # Calculate lifted parcel theta for use in iterative CINH loop below
    # RECALL: lifted parcel theta is CONSTANT from LPL to LCL
    theta_parcel = thermo.theta(pe2, tp2, 1000.)

    # Environmental theta and mixing ratio at LPL
    bltheta = thermo.theta(pres, interp.temp(pres, prof), 1000.)
    blmr = thermo.mixratio(pres, dwpt)

    # ACCUMULATED CINH IN MIXING LAYER BELOW THE LCL
    # This will be done in 10mb increments, and will use the virtual
    # temperature correction where possible
    pinc = -10
    a = int(lower)
    b = int(blupper)
    for pp in range(a, b, int(pinc)):
        pp1 = pp
        pp2 = pp + pinc
        if pp2 < blupper: pp2 = blupper
        dz = interp.hght(pp2, prof) - interp.hght(pp1, prof)

        # Calculate difference between Tv_parcel and Tv_environment at top
        # and bottom of 10mb layers. Make use of constant lifted parcel
        # theta and mixing ratio from LPL to LCL
        tv_env_bot = thermo.virtemp(
            pp1, thermo.theta(pp1, interp.temp(pp1, prof), 1000.),
            interp.dwpt(pp1, prof))
        tdef1 = (thermo.virtemp(pp1, theta_parcel,
            thermo.temp_at_mixrat(blmr, pp1)) - tv_env_bot) / \
            (thermo.ctok(tv_env_bot))

        tv_env_top = thermo.virtemp(
            pp2, thermo.theta(pp2, interp.temp(pp2, prof), 1000.),
            interp.dwpt(pp2, prof))
        tdef2 = (thermo.virtemp(pp2, theta_parcel,
            thermo.temp_at_mixrat(blmr, pp2)) - tv_env_top) / \
            (thermo.ctok(tv_env_bot))

        lyre = G * (tdef1 + tdef2) / 2. * dz
        if lyre < 0: totn += lyre

    # Move the bottom layer to the top of the boundary layer
    if lower > pe2:
        lower = pe2
        pcl.blayer = lower

    # Calculate height of various temperature levels
    p0c = temp_lvl(0., prof)
    pm10c = temp_lvl(-10., prof)
    pm20c = temp_lvl(-20., prof)
    pm30c = temp_lvl(-30., prof)
    hgt0c = interp.hght(p0c, prof)
    hgtm10c = interp.hght(pm10c, prof)
    hgtm20c = interp.hght(pm20c, prof)
    hgtm30c = interp.hght(pm30c, prof)
    pcl.p0c = p0c
    pcl.pm10c = pm10c
    pcl.pm20c = pm20c
    pcl.pm30c = pm30c
    pcl.hght0c = hgt0c
    pcl.hghtm10c = hgtm10c
    pcl.hghtm20c = hgtm20c
    pcl.hghtm30c = hgtm30c

    # Find lowest observation in layer
    i = 0
    while prof.gSndg[i][prof.pind] > lower:
        if i == prof.gNumLevels - 1: break
        i += 1
    while not QC(prof.gSndg[i][prof.tdind]):
        if i == prof.gNumLevels - 1: break
        i += 1
    lptr = i
    if prof.gSndg[i][prof.pind] == lower:
        if i != prof.gNumLevels - 1: lptr += 1

    # Find highest observation in layer
    i = prof.gNumLevels - 1
    while prof.gSndg[i][prof.pind] < upper:
        if i < lptr: break
        i -= 1
    uptr = i
    if prof.gSndg[i][prof.pind] == upper:
        if i > lptr: uptr -= 1

    # START WITH INTERPOLATED BOTTOM LAYER
    # Begin moist ascent from lifted parcel LCL (pe2, tp2)
    pe1 = lower
    h1 = interp.hght(pe1, prof)
    te1 = interp.vtmp(pe1, prof)
    tp1 = thermo.wetlift(pe2, tp2, pe1)
    lyre = 0
    lyrlast = 0
    for i in range(lptr, prof.gNumLevels):
        if not QC(prof.gSndg[i][prof.tind]): continue
        pe2 = prof.gSndg[i][prof.pind]
        h2 = prof.gSndg[i][prof.zind]
        te2 = interp.vtmp(pe2, prof)
        tp2 = thermo.wetlift(pe1, tp1, pe2)
        tdef1 = (thermo.virtemp(pe1, tp1, tp1) - te1) / thermo.ctok(te1)
        tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / thermo.ctok(te2)
        lyrlast = lyre
        lyre = G * (tdef1 + tdef2) / 2. * (h2 - h1)

        # Add layer energy to total positive if lyre > 0
        if lyre > 0:
            totp += lyre
            # Add layer energy to total negative if lyre < 0, only up to EL
        else:
            if pe2 > 500.: totn += lyre

        # Check for Max LI
        mli = thermo.virtemp(pe2, tp2, tp2) - te2
        if mli > li_max:
            li_max = mli
            li_maxpres = pe2

        # Check for Max Cap Strength
        mcap = te2 - mli
        if mcap > cap_strength:
            cap_strength = mcap
            cap_strengthpres = pe2

        tote += lyre
        pelast = pe1
        pe1 = pe2
        h1 = h2
        te1 = te2
        tp1 = tp2

        # Is this the top of the specified layer
        if i >= uptr and not QC(pcl.bplus):
            pe3 = pe1
            h3 = h1
            te3 = te1
            tp3 = tp1
            lyrf = lyre
            if lyrf > 0:
                pcl.bplus = totp - lyrf
                pcl.bminus = totn
            else:
                pcl.bplus = totp
                if pe2 > 500.: pcl.bminus = totn + lyrf
                else: pcl.bminus = totn
            pe2 = upper
            h2 = interp.hght(pe2, prof)
            te2 = interp.vtmp(pe2, prof)
            tp2 = thermo.wetlift(pe3, tp3, pe2)
            tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / thermo.ctok(te3)
            tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / thermo.ctok(te2)
            lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
            if lyrf > 0: pcl.bplus += lyrf
            else:
                if pe2 > 500.: pcl.bminus += lyrf
            if pcl.bplus == 0: pcl.bminus = 0.

        # Is this the freezing level
        if te2 < 0. and not QC(pcl.bfzl):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.bfzl = totp - lyrf
            else: pcl.bfzl = totp
            if not QC(p0c) or p0c > pe3:
                pcl.bfzl = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgt0c - h3)
                if lyrf > 0: pcl.bfzl += lyrf

        # Is this the -10C level
        if te2 < -10. and not QC(pcl.wm10c):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.wm10c = totp - lyrf
            else: pcl.wm10c = totp
            if not QC(pm10c) or pm10c > pcl.lclpres:
                pcl.wm10c = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgtm10c - h3)
                if lyrf > 0: pcl.wm10c += lyrf

        # Is this the -20C level
        if te2 < -20. and not QC(pcl.wm20c):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.wm20c = totp - lyrf
            else: pcl.wm20c = totp
            if not QC(pm20c) or pm20c > pcl.lclpres:
                pcl.wm20c = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgtm20c - h3)
                if lyrf > 0: pcl.wm20c += lyrf

        # Is this the -30C level
        if te2 < -30. and not QC(pcl.wm30c):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.wm30c = totp - lyrf
            else: pcl.wm30c = totp
            if not QC(pm30c) or pm30c > pcl.lclpres:
                pcl.wm30c = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgtm30c - h3)
                if lyrf > 0: pcl.wm30c += lyrf

        # Is this the 3km level
        if pcl.lclhght < 3000.:
            h = interp.agl(interp.hght(pe2, prof), prof)
            if h >= 3000. and not QC(pcl.b3km):
                pe3 = pelast
                h3 = interp.hght(pe3, prof)
                te3 = interp.vtmp(pe3, prof)
                tp3 = thermo.wetlift(pe1, tp1, pe3)
                lyrf = lyre
                if lyrf > 0: pcl.b3km = totp - lyrf
                else: pcl.b3km = totp
                h2 = interp.msl(3000., prof)
                pe2 = interp.pres(h2, prof)
                if QC(pe2):
                    te2 = interp.vtmp(pe2, prof)
                    tp2 = thermo.wetlift(pe3, tp3, pe2)
                    tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                        thermo.ctok(te3)
                    tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                        thermo.ctok(te2)
                    lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
                    if lyrf > 0: pcl.b3km += lyrf
        else: pcl.b3km = 0.

        # Is this the 6km level
        if pcl.lclhght < 6000.:
            h = interp.agl(interp.hght(pe2, prof), prof)
            if h >= 6000. and not QC(pcl.b6km):
                pe3 = pelast
                h3 = interp.hght(pe3, prof)
                te3 = interp.vtmp(pe3, prof)
                tp3 = thermo.wetlift(pe1, tp1, pe3)
                lyrf = lyre
                if lyrf > 0: pcl.b6km = totp - lyrf
                else: pcl.b6km = totp
                h2 = interp.msl(6000., prof)
                pe2 = interp.pres(h2, prof)
                if QC(pe2):
                    te2 = interp.vtmp(pe2, prof)
                    tp2 = thermo.wetlift(pe3, tp3, pe2)
                    tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                        thermo.ctok(te3)
                    tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                        thermo.ctok(te2)
                    lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
                    if lyrf > 0: pcl.b6km += lyrf
        else: pcl.b6km = 0.

        # LFC Possibility
        if lyre >= 0. and lyrlast <= 0.:
            tp3 = tp1
            te3 = te1
            pe2 = pe1
            pe3 = pelast
            while interp.vtmp(pe3, prof) > thermo.virtemp(
                    pe3, thermo.wetlift(pe2, tp3, pe3),
                    thermo.wetlift(pe2, tp3, pe3)):
                pe3 -= 5
            pcl.lfcpres = pe3
            pcl.lfchght = interp.agl(interp.hght(pe3, prof), prof)
            cinh_old = totn
            tote = 0.
            pcl.elpres = RMISSD
            li_max = RMISSD

            if cap_strength < 0.: cap_strength = 0.
            pcl.cap = cap_strength
            pcl.cappres = cap_strengthpres
            # Hack to force LFC to be at least at the LCL
            if pcl.lfcpres > pcl.lclpres:
                pcl.lfcpres = pcl.lclpres
                pcl.lfchght = pcl.lclhght

        # EL Possibility
        if lyre <= 0. and lyrlast >= 0.:
            tp3 = tp1
            te3 = te1
            pe2 = pe1
            pe3 = pelast
            while interp.vtmp(pe3, prof) < thermo.virtemp(
                    pe3, thermo.wetlift(pe2, tp3, pe3),
                    thermo.wetlift(pe2, tp3, pe3)):
                pe3 -= 5
            pcl.elpres = pe3
            pcl.elhght = interp.agl(interp.hght(pe3, prof), prof)
            pcl.mplpres = RMISSD
            pcl.limax = -li_max
            pcl.limaxpress = li_maxpres

        # MPL Possibility
        if tote < 0. and not QC(pcl.mplpres) and QC(pcl.elpres):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            totx = tote - lyre
            pe2 = pelast
            while totx > 0:
                pe2 -= 1
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                h2 = interp.hght(pe2, prof)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
                totx += lyrf
                tp3 = tp2
                te3 = te2
                pe3 = pe2
            pcl.mplpres = pe2
            pcl.mplhght = interp.agl(interp.hght(pe2, prof), prof)

        # 500 hPa Lifted Index
        if prof.gSndg[i][prof.pind] <= 500. and pcl.li5 == RMISSD:
            a = interp.vtmp(500., prof)
            b = thermo.wetlift(pe1, tp1, 500.)
            pcl.li5 = a - thermo.virtemp(500, b, b)

        # 300 hPa Lifted Index
        if prof.gSndg[i][prof.pind] <= 300. and pcl.li3 == RMISSD:
            a = interp.vtmp(300., prof)
            b = thermo.wetlift(pe1, tp1, 300.)
            pcl.li3 = a - thermo.virtemp(300, b, b)

    # Calculate BRN if available
    pcl = bulk_rich(pcl, prof)

    pcl.bminus = cinh_old
    if pcl.bplus == 0: pcl.bminus = 0.
    return pcl
コード例 #7
0
ファイル: params.py プロジェクト: WeatherGod/SHARPpy
def unstable_level(prof, lower, upper):
    '''
    Finds the most unstable level between the lower and upper levels.

    Inputs
    ------
        prof        (profile object)    Profile Object
        lower       (float)             Bottom level (hPa) [-1=SFC]
        upper       (float)             Top level (hPa) [-1=SFC-100hPa]

    Returns
    -------
        Pressure Level of most unstable level   (float [hPa])
    '''
    if lower == -1: lower = prof.gSndg[prof.sfc][prof.pind]
    if upper == -1: upper = prof.gSndg[prof.sfc][prof.pind] - 400.

    # Make sure this is a valid layer
    while not QC(interp.dwpt(upper, prof)): upper += 50.
    if not QC(interp.temp(lower, prof)): lower = prof.gSndg[prof.sfc][0]

    # Find lowest observations in the layer
    i = 0
    while prof.gSndg[i][prof.pind] > lower: i+=1
    while not QC(prof.gSndg[i][prof.tind]): i+=1
    lptr = i
    if prof.gSndg[i][prof.pind] == lower: lptr+=1

    # Find highest observations in the layer
    i = prof.gNumLevels - 1
    while prof.gSndg[i][prof.pind] < upper: i-=1
    uptr = i
    if prof.gSndg[i][prof.pind] == upper: uptr-=1

    # Start with interpolated bottom layer
    p1 = lower
    t1 = interp.temp(p1, prof)
    td1 = interp.dwpt(p1, prof)
    p2, t2 = thermo.drylift(p1, t1, td1)
    tmax = thermo.wetlift(p2, t2, 1000.)
    pmax = p1

    # Calculate every level that reports a dew point
    for i in range(lptr, uptr+1):
        if QC(prof.gSndg[i][prof.tdind]):
            p1 = prof.gSndg[i][prof.pind]
            t1 = prof.gSndg[i][prof.tind]
            td1 = prof.gSndg[i][prof.tdind]
            p2, t2 = thermo.drylift(p1, t1, td1)
            t1 = thermo.wetlift(p2, t2, 1000.)
            if t1 > tmax:
                tmax = t1
                pmax = p1

    # Finish with interpolated top layer
    p1 = upper
    t1 = interp.temp(p1, prof)
    td1 = interp.dwpt(p1, prof)
    p2, t2 = thermo.drylift(p1, t1, td1)
    t1 = thermo.wetlift(p2, t2, 1000.)
    if t1 > tmax:
        pmax = prof.gSndg[i][prof.pind]

    return pmax
コード例 #8
0
ファイル: params.py プロジェクト: WeatherGod/SHARPpy
def parcelx(lower, upper, pres, temp, dwpt, prof, **kwargs):
    '''
    Lifts the specified parcel, calculated various levels and parameters from
    the profile object. B+/B- are calculated based on the specified layer.

    !! All calculations use the virtual temperature correction unless noted. !!

    Inputs
    ------
        lower       (float)                 Lower-bound lifting level (hPa)
        upper       (float)                 Upper-bound lifting level
        pres        (float)                 Pressure of parcel to lift (hPa)
        temp        (float)                 Temperature of parcel to lift (C)
        dwpt        (float)                 Dew Point of parcel to lift (C)
        prof        (profile object)        Profile Object

    Returns
    -------
        pcl         (parcel object)         Parcel Object
    '''
    pcl = Parcel(-1, -1, pres, temp, dwpt)
    if 'lplvals' in kwargs: pcl.lplvals = kwargs.get('lplvals')
    else:
        lplvals = DefineParcel(prof, 5, pres=pres, temp=temp, dwpt=dwpt)
        pcl.lplvals = lplvals

    if prof.gNumLevels < 1: return pcl

    lyre = -1
    cap_strength = RMISSD
    cap_strengthpres = RMISSD
    li_max = RMISSD
    li_maxpres = RMISSD
    totp = 0.
    totn = 0.
    tote = 0.
    cinh_old = 0.

    # See if default layer is specified
    if lower == -1:
        lower = prof.gSndg[prof.sfc][prof.pind]
        pcl.blayer = lower
    if upper == -1:
        upper = prof.gSndg[prof.gNumLevels-1][prof.pind]
        pcl.tlayer = upper

    # Make sure that this is a valid layer
    if lower > pres:
        lower = pres
        pcl.blayer = lower
    if not QC(interp.vtmp(lower, prof)) or \
       not QC(interp.vtmp(upper, prof)):
        return RMISSD

    # Begin with the Mixing Layer
    te1 = interp.vtmp(pres, prof)
    pe1 = lower
    h1 = interp.hght(pe1, prof)
    tp1 = thermo.virtemp(pres, temp, dwpt)
    # te1 = tp1

    # Lift parcel and return LCL pres (hPa) and LCL temp (c)
    pe2, tp2 = thermo.drylift(pres, temp, dwpt)
    blupper = pe2       # Define top of layer as LCL pres
    h2 = interp.hght(pe2, prof)
    te2 = interp.vtmp(pe2, prof)
    pcl.lclpres = pe2
    pcl.lclhght = interp.agl(h2, prof)

    # Calculate lifted parcel theta for use in iterative CINH loop below
    # RECALL: lifted parcel theta is CONSTANT from LPL to LCL
    theta_parcel = thermo.theta(pe2, tp2, 1000.)

    # Environmental theta and mixing ratio at LPL
    bltheta = thermo.theta(pres, interp.temp(pres, prof), 1000.)
    blmr = thermo.mixratio(pres, dwpt)

    # ACCUMULATED CINH IN MIXING LAYER BELOW THE LCL
    # This will be done in 10mb increments, and will use the virtual
    # temperature correction where possible
    pinc = -10
    a = int(lower)
    b = int(blupper)
    for pp in range(a, b, int(pinc)):
        pp1 = pp
        pp2 = pp + pinc
        if pp2 < blupper: pp2 = blupper
        dz = interp.hght(pp2, prof) - interp.hght(pp1, prof)

        # Calculate difference between Tv_parcel and Tv_environment at top
        # and bottom of 10mb layers. Make use of constant lifted parcel
        # theta and mixing ratio from LPL to LCL
        tv_env_bot = thermo.virtemp(pp1, thermo.theta(pp1,
            interp.temp(pp1, prof), 1000.), interp.dwpt(pp1, prof))
        tdef1 = (thermo.virtemp(pp1, theta_parcel,
            thermo.temp_at_mixrat(blmr, pp1)) - tv_env_bot) / \
            (thermo.ctok(tv_env_bot))

        tv_env_top = thermo.virtemp(pp2, thermo.theta(pp2,
            interp.temp(pp2, prof), 1000.), interp.dwpt(pp2, prof))
        tdef2 = (thermo.virtemp(pp2, theta_parcel,
            thermo.temp_at_mixrat(blmr, pp2)) - tv_env_top) / \
            (thermo.ctok(tv_env_bot))

        lyre = G * (tdef1 + tdef2) / 2. * dz
        if lyre < 0: totn += lyre

    # Move the bottom layer to the top of the boundary layer
    if lower > pe2:
        lower = pe2
        pcl.blayer = lower

    # Calculate height of various temperature levels
    p0c = temp_lvl(0., prof)
    pm10c = temp_lvl(-10., prof)
    pm20c = temp_lvl(-20., prof)
    pm30c = temp_lvl(-30., prof)
    hgt0c = interp.hght(p0c, prof)
    hgtm10c = interp.hght(pm10c, prof)
    hgtm20c = interp.hght(pm20c, prof)
    hgtm30c = interp.hght(pm30c, prof)
    pcl.p0c = p0c
    pcl.pm10c = pm10c
    pcl.pm20c = pm20c
    pcl.pm30c = pm30c
    pcl.hght0c = hgt0c
    pcl.hghtm10c = hgtm10c
    pcl.hghtm20c = hgtm20c
    pcl.hghtm30c = hgtm30c

    # Find lowest observation in layer
    i = 0
    while prof.gSndg[i][prof.pind] > lower:
        if i == prof.gNumLevels-1: break
        i += 1
    while not QC(prof.gSndg[i][prof.tdind]):
        if i == prof.gNumLevels-1: break
        i += 1
    lptr = i
    if prof.gSndg[i][prof.pind] == lower:
        if i != prof.gNumLevels-1: lptr += 1

    # Find highest observation in layer
    i = prof.gNumLevels-1
    while prof.gSndg[i][prof.pind] < upper:
        if i < lptr: break
        i -= 1
    uptr = i
    if prof.gSndg[i][prof.pind] == upper:
        if i > lptr: uptr -= 1

    # START WITH INTERPOLATED BOTTOM LAYER
    # Begin moist ascent from lifted parcel LCL (pe2, tp2)
    pe1 = lower
    h1 = interp.hght(pe1, prof)
    te1 = interp.vtmp(pe1, prof)
    tp1 = thermo.wetlift(pe2, tp2, pe1)
    lyre = 0
    lyrlast = 0
    for i in range(lptr, prof.gNumLevels):
        if not QC(prof.gSndg[i][prof.tind]): continue
        pe2 = prof.gSndg[i][prof.pind]
        h2 = prof.gSndg[i][prof.zind]
        te2 = interp.vtmp(pe2, prof)
        tp2 = thermo.wetlift(pe1, tp1, pe2)
        tdef1 = (thermo.virtemp(pe1, tp1, tp1) - te1) / thermo.ctok(te1)
        tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / thermo.ctok(te2)
        lyrlast = lyre
        lyre = G * (tdef1 + tdef2) / 2. * (h2 - h1)

        # Add layer energy to total positive if lyre > 0
        if lyre > 0: totp += lyre
        # Add layer energy to total negative if lyre < 0, only up to EL
        else:
            if pe2 > 500.: totn += lyre

        # Check for Max LI
        mli = thermo.virtemp(pe2, tp2, tp2) - te2
        if  mli > li_max:
            li_max = mli
            li_maxpres = pe2

        # Check for Max Cap Strength
        mcap = te2 - mli
        if mcap > cap_strength:
            cap_strength = mcap
            cap_strengthpres = pe2

        tote += lyre
        pelast = pe1
        pe1 = pe2
        h1 = h2
        te1 = te2
        tp1 = tp2

        # Is this the top of the specified layer
        if i >= uptr and not QC(pcl.bplus):
            pe3 = pe1
            h3 = h1
            te3 = te1
            tp3 = tp1
            lyrf = lyre
            if lyrf > 0:
                pcl.bplus = totp - lyrf
                pcl.bminus = totn
            else:
                pcl.bplus = totp
                if pe2 > 500.: pcl.bminus = totn + lyrf
                else: pcl.bminus = totn
            pe2 = upper
            h2 = interp.hght(pe2, prof)
            te2 = interp.vtmp(pe2, prof)
            tp2 = thermo.wetlift(pe3, tp3, pe2)
            tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / thermo.ctok(te3)
            tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / thermo.ctok(te2)
            lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
            if lyrf > 0: pcl.bplus += lyrf
            else:
                if pe2 > 500.: pcl.bminus += lyrf
            if pcl.bplus == 0: pcl.bminus = 0.

        # Is this the freezing level
        if te2 < 0. and not QC(pcl.bfzl):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.bfzl = totp - lyrf
            else: pcl.bfzl = totp
            if not QC(p0c) or p0c > pe3:
                pcl.bfzl = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgt0c - h3)
                if lyrf > 0: pcl.bfzl += lyrf

        # Is this the -10C level
        if te2 < -10. and not QC(pcl.wm10c):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.wm10c = totp - lyrf
            else: pcl.wm10c = totp
            if not QC(pm10c) or pm10c > pcl.lclpres:
                pcl.wm10c = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgtm10c - h3)
                if lyrf > 0: pcl.wm10c += lyrf

        # Is this the -20C level
        if te2 < -20. and not QC(pcl.wm20c):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.wm20c = totp - lyrf
            else: pcl.wm20c = totp
            if not QC(pm20c) or pm20c > pcl.lclpres:
                pcl.wm20c = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgtm20c - h3)
                if lyrf > 0: pcl.wm20c += lyrf

        # Is this the -30C level
        if te2 < -30. and not QC(pcl.wm30c):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            lyrf = lyre
            if lyrf > 0.: pcl.wm30c = totp - lyrf
            else: pcl.wm30c = totp
            if not QC(pm30c) or pm30c > pcl.lclpres:
                pcl.wm30c = 0
            elif QC(pe2):
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (hgtm30c - h3)
                if lyrf > 0: pcl.wm30c += lyrf

        # Is this the 3km level
        if pcl.lclhght < 3000.:
            h = interp.agl(interp.hght(pe2, prof), prof)
            if h >= 3000. and not QC(pcl.b3km):
                pe3 = pelast
                h3 = interp.hght(pe3, prof)
                te3 = interp.vtmp(pe3, prof)
                tp3 = thermo.wetlift(pe1, tp1, pe3)
                lyrf = lyre
                if lyrf > 0: pcl.b3km = totp - lyrf
                else: pcl.b3km = totp
                h2 = interp.msl(3000., prof)
                pe2 = interp.pres(h2, prof)
                if QC(pe2):
                    te2 = interp.vtmp(pe2, prof)
                    tp2 = thermo.wetlift(pe3, tp3, pe2)
                    tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                        thermo.ctok(te3)
                    tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                        thermo.ctok(te2)
                    lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
                    if lyrf > 0: pcl.b3km += lyrf
        else: pcl.b3km = 0.

        # Is this the 6km level
        if pcl.lclhght < 6000.:
            h = interp.agl(interp.hght(pe2, prof), prof)
            if h >= 6000. and not QC(pcl.b6km):
                pe3 = pelast
                h3 = interp.hght(pe3, prof)
                te3 = interp.vtmp(pe3, prof)
                tp3 = thermo.wetlift(pe1, tp1, pe3)
                lyrf = lyre
                if lyrf > 0: pcl.b6km = totp - lyrf
                else: pcl.b6km = totp
                h2 = interp.msl(6000., prof)
                pe2 = interp.pres(h2, prof)
                if QC(pe2):
                    te2 = interp.vtmp(pe2, prof)
                    tp2 = thermo.wetlift(pe3, tp3, pe2)
                    tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                        thermo.ctok(te3)
                    tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                        thermo.ctok(te2)
                    lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
                    if lyrf > 0: pcl.b6km += lyrf
        else: pcl.b6km = 0.

        # LFC Possibility
        if lyre >= 0. and lyrlast <= 0.:
            tp3 = tp1
            te3 = te1
            pe2 = pe1
            pe3 = pelast
            while interp.vtmp(pe3, prof) > thermo.virtemp(pe3,
                thermo.wetlift(pe2, tp3, pe3), thermo.wetlift(pe2, tp3, pe3)):
                    pe3 -= 5
            pcl.lfcpres = pe3
            pcl.lfchght = interp.agl(interp.hght(pe3, prof), prof)
            cinh_old = totn
            tote = 0.
            pcl.elpres = RMISSD
            li_max = RMISSD

            if cap_strength < 0.: cap_strength = 0.
            pcl.cap = cap_strength
            pcl.cappres = cap_strengthpres
            # Hack to force LFC to be at least at the LCL
            if pcl.lfcpres > pcl.lclpres:
                pcl.lfcpres = pcl.lclpres
                pcl.lfchght = pcl.lclhght

        # EL Possibility
        if lyre <= 0. and lyrlast >= 0.:
            tp3 = tp1
            te3 = te1
            pe2 = pe1
            pe3 = pelast
            while interp.vtmp(pe3, prof) < thermo.virtemp(pe3,
                thermo.wetlift(pe2, tp3, pe3), thermo.wetlift(pe2, tp3, pe3)):
                    pe3 -= 5
            pcl.elpres = pe3
            pcl.elhght = interp.agl(interp.hght(pe3, prof), prof)
            pcl.mplpres = RMISSD
            pcl.limax = -li_max
            pcl.limaxpress = li_maxpres

        # MPL Possibility
        if tote < 0. and not QC(pcl.mplpres) and QC(pcl.elpres):
            pe3 = pelast
            h3 = interp.hght(pe3, prof)
            te3 = interp.vtmp(pe3, prof)
            tp3 = thermo.wetlift(pe1, tp1, pe3)
            totx = tote - lyre
            pe2 = pelast
            while totx > 0:
                pe2 -= 1
                te2 = interp.vtmp(pe2, prof)
                tp2 = thermo.wetlift(pe3, tp3, pe2)
                h2 = interp.hght(pe2, prof)
                tdef3 = (thermo.virtemp(pe3, tp3, tp3) - te3) / \
                    thermo.ctok(te3)
                tdef2 = (thermo.virtemp(pe2, tp2, tp2) - te2) / \
                    thermo.ctok(te2)
                lyrf = G * (tdef3 + tdef2) / 2. * (h2 - h3)
                totx += lyrf
                tp3 = tp2
                te3 = te2
                pe3 = pe2
            pcl.mplpres = pe2
            pcl.mplhght = interp.agl(interp.hght(pe2, prof), prof)

        # 500 hPa Lifted Index
        if prof.gSndg[i][prof.pind] <= 500. and pcl.li5 == RMISSD:
            a = interp.vtmp(500., prof)
            b = thermo.wetlift(pe1, tp1, 500.)
            pcl.li5 = a - thermo.virtemp(500, b, b)

        # 300 hPa Lifted Index
        if prof.gSndg[i][prof.pind] <= 300. and pcl.li3 == RMISSD:
            a = interp.vtmp(300., prof)
            b = thermo.wetlift(pe1, tp1, 300.)
            pcl.li3 = a - thermo.virtemp(300, b, b)

    # Calculate BRN if available
    pcl = bulk_rich(pcl, prof)

    pcl.bminus = cinh_old
    if pcl.bplus == 0: pcl.bminus = 0.
    return pcl
コード例 #9
0
def do_sharppy(spc_file):
    """
    Based on the tutorial which can be found here: http://nbviewer.ipython.org/github/sharppy/SHARPpy/blob/master/tutorials/SHARPpy_basics.ipynb
    SHARPpy can be found here: https://github.com/sharppy/SHARPpy
    Credit goes to:
    Patrick Marsh (SPC)
    Kelton Halbert (OU School of Meteorology)
    Greg Blumberg (OU/CIMMS)
    Tim Supinie (OU School of Meteorology)
    
    """
    import sharppy
    import sharppy.sharptab.profile as profile
    import sharppy.sharptab.interp as interp
    import sharppy.sharptab.winds as winds
    import sharppy.sharptab.utils as utils
    import sharppy.sharptab.params as params
    import sharppy.sharptab.thermo as thermo
    import matplotlib.pyplot as plt
    from StringIO import StringIO
    from matplotlib.axes import Axes
    import matplotlib.transforms as transforms
    import matplotlib.axis as maxis
    import matplotlib.spines as mspines
    import matplotlib.path as mpath
    from matplotlib.projections import register_projection

    spc_file = open('skewt_data', 'r').read()

    def parseSPC(spc_file):
        ## read in the file
        data = np.array([l.strip() for l in spc_file.split('\n')])

        ## necessary index points
        title_idx = np.where(data == '%TITLE%')[0][0]
        start_idx = np.where(data == '%RAW%')[0] + 1
        finish_idx = np.where(data == '%END%')[0]

        ## create the plot title
        data_header = data[title_idx + 1].split()
        location = data_header[0] + ' ' + data_header[1]
        time = data_header[2]
        title = location + ' ' + time
        ## put it all together for StringIO
        full_data = '\n'.join(data[start_idx:finish_idx][:])
        sound_data = StringIO(full_data)

        ## read the data into arrays
        p, h, T, Td, wdir, wspd = np.genfromtxt(sound_data,
                                                delimiter=',',
                                                comments="%",
                                                unpack=True)

        return p, h, T, Td, wdir, wspd, title

    pres, hght, tmpc, dwpc, wdir, wspd, title = parseSPC(spc_file)
    prof = profile.create_profile(profile='default', pres=pres, hght=hght, tmpc=tmpc, \
    dwpc=dwpc, wspd=wspd, wdir=wdir, missing=-9999, strictQC=True)

    sfcpcl = params.parcelx(prof, flag=1)  # Surface Parcel
    fcstpcl = params.parcelx(prof, flag=2)  # Forecast Parcel
    mupcl = params.parcelx(prof, flag=3)  # Most-Unstable Parcel
    mlpcl = params.parcelx(prof, flag=4)  # 100 mb Mean Layer Parcel

    msl_hght = prof.hght[prof.sfc]  # Grab the surface height value
    print "SURFACE HEIGHT (m MSL):", msl_hght
    agl_hght = interp.to_agl(prof, msl_hght)  # Converts to AGL
    print "SURFACE HEIGHT (m AGL):", agl_hght
    msl_hght = interp.to_msl(prof, agl_hght)  # Converts to MSL
    print "SURFACE HEIGHT (m MSL):", msl_hght
    print "Most-Unstable CAPE:", mupcl.bplus  # J/kg
    print "Most-Unstable CIN:", mupcl.bminus  # J/kg
    print "Most-Unstable LCL:", mupcl.lclhght  # meters AGL
    print "Most-Unstable LFC:", mupcl.lfchght  # meters AGL
    print "Most-Unstable EL:", mupcl.elhght  # meters AGL
    print "Most-Unstable LI:", mupcl.li5  # C

    class SkewXTick(maxis.XTick):
        def draw(self, renderer):
            if not self.get_visible(): return
            renderer.open_group(self.__name__)

            lower_interval = self.axes.xaxis.lower_interval
            upper_interval = self.axes.xaxis.upper_interval

            if self.gridOn and transforms.interval_contains(
                    self.axes.xaxis.get_view_interval(), self.get_loc()):
                self.gridline.draw(renderer)

            if transforms.interval_contains(lower_interval, self.get_loc()):
                if self.tick1On:
                    self.tick1line.draw(renderer)
                if self.label1On:
                    self.label1.draw(renderer)

            if transforms.interval_contains(upper_interval, self.get_loc()):
                if self.tick2On:
                    self.tick2line.draw(renderer)
                if self.label2On:
                    self.label2.draw(renderer)

            renderer.close_group(self.__name__)

    # This class exists to provide two separate sets of intervals to the tick,
    # as well as create instances of the custom tick
    class SkewXAxis(maxis.XAxis):
        def __init__(self, *args, **kwargs):
            maxis.XAxis.__init__(self, *args, **kwargs)
            self.upper_interval = 0.0, 1.0

        def _get_tick(self, major):
            return SkewXTick(self.axes, 0, '', major=major)

        @property
        def lower_interval(self):
            return self.axes.viewLim.intervalx

        def get_view_interval(self):
            return self.upper_interval[0], self.axes.viewLim.intervalx[1]

    # This class exists to calculate the separate data range of the
    # upper X-axis and draw the spine there. It also provides this range
    # to the X-axis artist for ticking and gridlines
    class SkewSpine(mspines.Spine):
        def _adjust_location(self):
            trans = self.axes.transDataToAxes.inverted()
            if self.spine_type == 'top':
                yloc = 1.0
            else:
                yloc = 0.0
            left = trans.transform_point((0.0, yloc))[0]
            right = trans.transform_point((1.0, yloc))[0]

            pts = self._path.vertices
            pts[0, 0] = left
            pts[1, 0] = right
            self.axis.upper_interval = (left, right)

    # This class handles registration of the skew-xaxes as a projection as well
    # as setting up the appropriate transformations. It also overrides standard
    # spines and axes instances as appropriate.
    class SkewXAxes(Axes):
        # The projection must specify a name.  This will be used be the
        # user to select the projection, i.e. ``subplot(111,
        # projection='skewx')``.
        name = 'skewx'

        def _init_axis(self):
            #Taken from Axes and modified to use our modified X-axis
            self.xaxis = SkewXAxis(self)
            self.spines['top'].register_axis(self.xaxis)
            self.spines['bottom'].register_axis(self.xaxis)
            self.yaxis = maxis.YAxis(self)
            self.spines['left'].register_axis(self.yaxis)
            self.spines['right'].register_axis(self.yaxis)

        def _gen_axes_spines(self):
            spines = {
                'top': SkewSpine.linear_spine(self, 'top'),
                'bottom': mspines.Spine.linear_spine(self, 'bottom'),
                'left': mspines.Spine.linear_spine(self, 'left'),
                'right': mspines.Spine.linear_spine(self, 'right')
            }
            return spines

        def _set_lim_and_transforms(self):
            """
            This is called once when the plot is created to set up all the
            transforms for the data, text and grids.
            """
            rot = 30

            #Get the standard transform setup from the Axes base class
            Axes._set_lim_and_transforms(self)

            # Need to put the skew in the middle, after the scale and limits,
            # but before the transAxes. This way, the skew is done in Axes
            # coordinates thus performing the transform around the proper origin
            # We keep the pre-transAxes transform around for other users, like the
            # spines for finding bounds
            self.transDataToAxes = self.transScale + (
                self.transLimits + transforms.Affine2D().skew_deg(rot, 0))

            # Create the full transform from Data to Pixels
            self.transData = self.transDataToAxes + self.transAxes

            # Blended transforms like this need to have the skewing applied using
            # both axes, in axes coords like before.
            self._xaxis_transform = (
                transforms.blended_transform_factory(
                    self.transScale + self.transLimits,
                    transforms.IdentityTransform()) +
                transforms.Affine2D().skew_deg(rot, 0)) + self.transAxes

    # Now register the projection with matplotlib so the user can select
    # it.
    register_projection(SkewXAxes)

    pcl = mupcl
    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(6.5875, 6.2125))
    ax = fig.add_subplot(111, projection='skewx')
    ax.grid(True)

    pmax = 1000
    pmin = 10
    dp = -10
    presvals = np.arange(int(pmax), int(pmin) + dp, dp)

    # plot the moist-adiabats
    for t in np.arange(-10, 45, 5):
        tw = []
        for p in presvals:
            tw.append(thermo.wetlift(1000., t, p))
        ax.semilogy(tw, presvals, 'k-', alpha=.2)

    def thetas(theta, presvals):
        return ((theta + thermo.ZEROCNK) / (np.power(
            (1000. / presvals), thermo.ROCP))) - thermo.ZEROCNK

    # plot the dry adiabats
    for t in np.arange(-50, 110, 10):
        ax.semilogy(thetas(t, presvals), presvals, 'r-', alpha=.2)

    plt.title(title, fontsize=14, loc='left')
    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dicatated by the typical meteorological plot
    ax.semilogy(prof.tmpc, prof.pres, 'r', lw=2)
    ax.semilogy(prof.dwpc, prof.pres, 'g', lw=2)
    ax.semilogy(pcl.ttrace, pcl.ptrace, 'k-.', lw=2)

    # An example of a slanted line at constant X
    l = ax.axvline(0, color='b', linestyle='--')
    l = ax.axvline(-20, color='b', linestyle='--')

    # Disables the log-formatting that comes with semilogy
    ax.yaxis.set_major_formatter(plt.ScalarFormatter())
    ax.set_yticks(np.linspace(100, 1000, 10))
    ax.set_ylim(1050, 100)

    ax.xaxis.set_major_locator(plt.MultipleLocator(10))
    ax.set_xlim(-50, 50)
    plt.show()

    ##PLOTS SKEWT OK ABOVE HERE ##
    """
コード例 #10
0
ファイル: plot_funcs.py プロジェクト: liamtill/wrfplot
def do_sharppy(spc_file):
    """
    Based on the tutorial which can be found here: http://nbviewer.ipython.org/github/sharppy/SHARPpy/blob/master/tutorials/SHARPpy_basics.ipynb
    SHARPpy can be found here: https://github.com/sharppy/SHARPpy
    Credit goes to:
    Patrick Marsh (SPC)
    Kelton Halbert (OU School of Meteorology)
    Greg Blumberg (OU/CIMMS)
    Tim Supinie (OU School of Meteorology)
    
    """
    import sharppy
    import sharppy.sharptab.profile as profile
    import sharppy.sharptab.interp as interp
    import sharppy.sharptab.winds as winds
    import sharppy.sharptab.utils as utils
    import sharppy.sharptab.params as params
    import sharppy.sharptab.thermo as thermo
    import matplotlib.pyplot as plt
    from StringIO import StringIO
    from matplotlib.axes import Axes
    import matplotlib.transforms as transforms
    import matplotlib.axis as maxis
    import matplotlib.spines as mspines
    import matplotlib.path as mpath
    from matplotlib.projections import register_projection
    
    spc_file = open('skewt_data', 'r').read()


    def parseSPC(spc_file):
        ## read in the file
        data = np.array([l.strip() for l in spc_file.split('\n')])

        ## necessary index points
        title_idx = np.where( data == '%TITLE%')[0][0]
        start_idx = np.where( data == '%RAW%' )[0] + 1
        finish_idx = np.where( data == '%END%')[0]
    
        ## create the plot title
        data_header = data[title_idx + 1].split()
        location = data_header[0]+' '+data_header[1]
        time = data_header[2]
        title = location+' '+time
        ## put it all together for StringIO
        full_data = '\n'.join(data[start_idx : finish_idx][:])
        sound_data = StringIO( full_data )
    
        ## read the data into arrays
        p, h, T, Td, wdir, wspd = np.genfromtxt( sound_data, delimiter=',', comments="%", unpack=True )
    
        return p, h, T, Td, wdir, wspd, title
        
    pres, hght, tmpc, dwpc, wdir, wspd, title = parseSPC(spc_file)
    prof = profile.create_profile(profile='default', pres=pres, hght=hght, tmpc=tmpc, \
    dwpc=dwpc, wspd=wspd, wdir=wdir, missing=-9999, strictQC=True)
    
    sfcpcl = params.parcelx( prof, flag=1 ) # Surface Parcel
    fcstpcl = params.parcelx( prof, flag=2 ) # Forecast Parcel
    mupcl = params.parcelx( prof, flag=3 ) # Most-Unstable Parcel
    mlpcl = params.parcelx( prof, flag=4 ) # 100 mb Mean Layer Parcel
         
    msl_hght = prof.hght[prof.sfc] # Grab the surface height value
    print "SURFACE HEIGHT (m MSL):",msl_hght
    agl_hght = interp.to_agl(prof, msl_hght) # Converts to AGL
    print "SURFACE HEIGHT (m AGL):", agl_hght
    msl_hght = interp.to_msl(prof, agl_hght) # Converts to MSL
    print "SURFACE HEIGHT (m MSL):",msl_hght
    print "Most-Unstable CAPE:", mupcl.bplus # J/kg
    print "Most-Unstable CIN:", mupcl.bminus # J/kg
    print "Most-Unstable LCL:", mupcl.lclhght # meters AGL
    print "Most-Unstable LFC:", mupcl.lfchght # meters AGL
    print "Most-Unstable EL:", mupcl.elhght # meters AGL
    print "Most-Unstable LI:", mupcl.li5 # C
    
    class SkewXTick(maxis.XTick):
        def draw(self, renderer):
            if not self.get_visible(): return
            renderer.open_group(self.__name__)
    
            lower_interval = self.axes.xaxis.lower_interval
            upper_interval = self.axes.xaxis.upper_interval
    
            if self.gridOn and transforms.interval_contains(
                    self.axes.xaxis.get_view_interval(), self.get_loc()):
                self.gridline.draw(renderer)
    
            if transforms.interval_contains(lower_interval, self.get_loc()):
                if self.tick1On:
                    self.tick1line.draw(renderer)
                if self.label1On:
                    self.label1.draw(renderer)
    
            if transforms.interval_contains(upper_interval, self.get_loc()):
                if self.tick2On:
                    self.tick2line.draw(renderer)
                if self.label2On:
                    self.label2.draw(renderer)
    
            renderer.close_group(self.__name__)
    
    
    # This class exists to provide two separate sets of intervals to the tick,
    # as well as create instances of the custom tick
    class SkewXAxis(maxis.XAxis):
        def __init__(self, *args, **kwargs):
            maxis.XAxis.__init__(self, *args, **kwargs)
            self.upper_interval = 0.0, 1.0
    
        def _get_tick(self, major):
            return SkewXTick(self.axes, 0, '', major=major)
    
        @property
        def lower_interval(self):
            return self.axes.viewLim.intervalx
    
        def get_view_interval(self):
            return self.upper_interval[0], self.axes.viewLim.intervalx[1]
    
    
    # This class exists to calculate the separate data range of the
    # upper X-axis and draw the spine there. It also provides this range
    # to the X-axis artist for ticking and gridlines
    class SkewSpine(mspines.Spine):
        def _adjust_location(self):
            trans = self.axes.transDataToAxes.inverted()
            if self.spine_type == 'top':
                yloc = 1.0
            else:
                yloc = 0.0
            left = trans.transform_point((0.0, yloc))[0]
            right = trans.transform_point((1.0, yloc))[0]
    
            pts  = self._path.vertices
            pts[0, 0] = left
            pts[1, 0] = right
            self.axis.upper_interval = (left, right)
    
    
    # This class handles registration of the skew-xaxes as a projection as well
    # as setting up the appropriate transformations. It also overrides standard
    # spines and axes instances as appropriate.
    class SkewXAxes(Axes):
        # The projection must specify a name.  This will be used be the
        # user to select the projection, i.e. ``subplot(111,
        # projection='skewx')``.
        name = 'skewx'
    
        def _init_axis(self):
            #Taken from Axes and modified to use our modified X-axis
            self.xaxis = SkewXAxis(self)
            self.spines['top'].register_axis(self.xaxis)
            self.spines['bottom'].register_axis(self.xaxis)
            self.yaxis = maxis.YAxis(self)
            self.spines['left'].register_axis(self.yaxis)
            self.spines['right'].register_axis(self.yaxis)
    
        def _gen_axes_spines(self):
            spines = {'top':SkewSpine.linear_spine(self, 'top'),
                      'bottom':mspines.Spine.linear_spine(self, 'bottom'),
                      'left':mspines.Spine.linear_spine(self, 'left'),
                      'right':mspines.Spine.linear_spine(self, 'right')}
            return spines
    
        def _set_lim_and_transforms(self):
            """
            This is called once when the plot is created to set up all the
            transforms for the data, text and grids.
            """
            rot = 30
    
            #Get the standard transform setup from the Axes base class
            Axes._set_lim_and_transforms(self)
    
            # Need to put the skew in the middle, after the scale and limits,
            # but before the transAxes. This way, the skew is done in Axes
            # coordinates thus performing the transform around the proper origin
            # We keep the pre-transAxes transform around for other users, like the
            # spines for finding bounds
            self.transDataToAxes = self.transScale + (self.transLimits +
                    transforms.Affine2D().skew_deg(rot, 0))
    
            # Create the full transform from Data to Pixels
            self.transData = self.transDataToAxes + self.transAxes
    
            # Blended transforms like this need to have the skewing applied using
            # both axes, in axes coords like before.
            self._xaxis_transform = (transforms.blended_transform_factory(
                        self.transScale + self.transLimits,
                        transforms.IdentityTransform()) +
                    transforms.Affine2D().skew_deg(rot, 0)) + self.transAxes
    
    # Now register the projection with matplotlib so the user can select
    # it.
    register_projection(SkewXAxes)
    
    pcl = mupcl
    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(6.5875, 6.2125))
    ax = fig.add_subplot(111, projection='skewx')
    ax.grid(True)
    
    pmax = 1000
    pmin = 10
    dp = -10
    presvals = np.arange(int(pmax), int(pmin)+dp, dp)
    
    # plot the moist-adiabats
    for t in np.arange(-10,45,5):
        tw = []
        for p in presvals:
            tw.append(thermo.wetlift(1000., t, p))
        ax.semilogy(tw, presvals, 'k-', alpha=.2)
    
    def thetas(theta, presvals):
        return ((theta + thermo.ZEROCNK) / (np.power((1000. / presvals),thermo.ROCP))) - thermo.ZEROCNK
    
    # plot the dry adiabats
    for t in np.arange(-50,110,10):
        ax.semilogy(thetas(t, presvals), presvals, 'r-', alpha=.2)
    
    plt.title(title, fontsize=14, loc='left')
    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dicatated by the typical meteorological plot
    ax.semilogy(prof.tmpc, prof.pres, 'r', lw=2)
    ax.semilogy(prof.dwpc, prof.pres, 'g', lw=2)
    ax.semilogy(pcl.ttrace, pcl.ptrace, 'k-.', lw=2)
    
    # An example of a slanted line at constant X
    l = ax.axvline(0, color='b', linestyle='--')
    l = ax.axvline(-20, color='b', linestyle='--')
    
    # Disables the log-formatting that comes with semilogy
    ax.yaxis.set_major_formatter(plt.ScalarFormatter())
    ax.set_yticks(np.linspace(100,1000,10))
    ax.set_ylim(1050,100)
    
    ax.xaxis.set_major_locator(plt.MultipleLocator(10))
    ax.set_xlim(-50,50)
    plt.show()
    
    ##PLOTS SKEWT OK ABOVE HERE ##
    """
コード例 #11
0
def append_wbz():
    #Load each ERA-Interim netcdf file, and append wbz

    start_lat = -44.525
    end_lat = -9.975
    start_lon = 111.975
    end_lon = 156.275
    domain = [start_lat, end_lat, start_lon, end_lon]
    model = "erai"
    region = "aus"
    dates = []
    for y in np.arange(1979, 2019):
        for m in [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]:
            if (m != 12):
                dates.append([dt.datetime(y,m,1,0,0,0),\
                 dt.datetime(y,m+1,1,0,0,0)-dt.timedelta(hours = 6)])
            else:
                dates.append([dt.datetime(y,m,1,0,0,0),\
                 dt.datetime(y+1,1,1,0,0,0)-dt.timedelta(hours = 6)])
    for t in np.arange(0, len(dates)):
        print(str(dates[t][0]) + " - " + str(dates[t][1]))

        fname = "/g/data/eg3/ab4502/ExtremeWind/"+region+"/"+model+"/"+model+"_"+\
         dt.datetime.strftime(dates[t][0],"%Y%m%d")+"_"+\
         dt.datetime.strftime(dates[t][-1],"%Y%m%d")+".nc"

        ta,dp,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,cp,wg10,cape,lon,lat,date_list = \
         read_erai(domain,dates[t])

        dp = get_dp(ta, hur, dp_mask=False)

        agl_idx = (p <= ps)

        #Replace masked dp values
        dp = replace_dp(dp)
        try:
            prof = profile.create_profile(pres = np.insert(p[agl_idx],0,ps), \
             hght = np.insert(hgt[agl_idx],0,terrain), \
             tmpc = np.insert(ta[agl_idx],0,tas), \
             dwpc = np.insert(dp[agl_idx],0,ta2d), \
             u = np.insert(ua[agl_idx],0,uas), \
             v = np.insert(va[agl_idx],0,vas), \
             strictqc=False, omeg=np.insert(wap[agl_idx],0,wap[agl_idx][0]) )
        except:
            p = p[agl_idx]
            ua = ua[agl_idx]
            va = va[agl_idx]
            hgt = hgt[agl_idx]
            ta = ta[agl_idx]             \
               dp = dp[agl_idx]
            p[0] = ps
            ua[0] = uas
            va[0] = vas
            hgt[0] = terrain
            ta[0] = tas
            dp[0] = ta2d
            prof = profile.create_profile(pres = p, \
             hght = hgt, \
             tmpc = ta, \
             dwpc = dp, \
             u = ua, \
             v = va, \
             strictqc=False, omeg=wap[agl_idx])

        pwb0 = params.temp_lvl(prof, 0, wetbulb=True)
        hwb0 = interp.to_agl(prof, interp.hght(prof, pwb0))

        param_file = nc.Dataset(fname, "a")
        wbz_var = param_file.createVariable("wbz",float,\
        ("time","lat","lon"))
        wbz_var.units = "m"
        wbz_var.long_name = "wet_bulb_zero_height"
        wbz_var[:] = hwb0

        T1 = abs(
            thermo.wetlift(prof.pres[0], prof.tmpc[0], 600) -
            interp.temp(prof, 600))
        T2 = abs(
            thermo.wetlift(pwb0, interp.temp(prof, pwb0), sfc) - prof.tmpc[0])
        Vprime = utils.KTS2MS(13 * np.sqrt((T1 + T2) / 2) + (1 / 3 *
                                                             (Umean01)))

        Vprime_var = param_file.createVariable("Vprime",float,\
        ("time","lat","lon"))
        Vprime_var.units = "m/s"
        Vprime_var.long_name = "miller_1972_wind_speed"
        Vprime_var[:] = Vprime

        param_file.close()