예제 #1
0
def plot_sounding(date, station):
    p, T, Td, u, v, windspeed = get_sounding_data(date, station)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    lfc_pressure, lfc_temperature = mpcalc.lfc(p, T, Td)
    parcel_path = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(8, 8))
    skew = SkewT(fig)

    # Plot the data
    temperature_line, = skew.plot(p, T, color='tab:red')
    dewpoint_line, = skew.plot(p, Td, color='blue')
    cursor = mplcursors.cursor([temperature_line, dewpoint_line])

    # Plot thermodynamic parameters and parcel path
    skew.plot(p, parcel_path, color='black')

    if lcl_pressure:
        skew.ax.axhline(lcl_pressure, color='black')

    if lfc_pressure:
        skew.ax.axhline(lfc_pressure, color='0.7')

    # Add the relevant special lines
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    # Shade areas representing CAPE and CIN
    skew.shade_cin(p, T, parcel_path)
    skew.shade_cape(p, T, parcel_path)

    # Add wind barbs
    skew.plot_barbs(p, u, v)

    # Add an axes to the plot
    ax_hod = inset_axes(skew.ax, '30%', '30%', loc=1, borderpad=3)

    # Plot the hodograph
    h = Hodograph(ax_hod, component_range=100.)

    # Grid the hodograph
    h.add_grid(increment=20)

    # Plot the data on the hodograph
    mask = (p >= 100 * units.mbar)
    h.plot_colormapped(u[mask], v[mask],
                       windspeed[mask])  # Plot a line colored by wind speed

    # Set some sensible axis limits
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    return fig, skew
예제 #2
0
def plot_sounding(date, station):
    p, T, Td, u, v, windspeed = get_sounding_data(date, station)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    lfc_pressure, lfc_temperature = mpcalc.lfc(p, T, Td)
    parcel_path = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(8, 8))
    skew = SkewT(fig)

    # Plot the data
    temperature_line, = skew.plot(p, T, color='tab:red')
    dewpoint_line, = skew.plot(p, Td, color='blue')
    cursor = mplcursors.cursor([temperature_line, dewpoint_line])

    # Plot thermodynamic parameters and parcel path
    skew.plot(p, parcel_path, color='black')

    if lcl_pressure:
        skew.ax.axhline(lcl_pressure, color='black')

    if lfc_pressure:
        skew.ax.axhline(lfc_pressure, color='0.7')

    # Add the relevant special lines
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    # Shade areas representing CAPE and CIN
    skew.shade_cin(p, T, parcel_path)
    skew.shade_cape(p, T, parcel_path)

    # Add wind barbs
    skew.plot_barbs(p, u, v)

    # Add an axes to the plot
    ax_hod = inset_axes(skew.ax, '30%', '30%', loc=1, borderpad=3)

    # Plot the hodograph
    h = Hodograph(ax_hod, component_range=100.)

    # Grid the hodograph
    h.add_grid(increment=20)

    # Plot the data on the hodograph
    mask = (p >= 100 * units.mbar)
    h.plot_colormapped(u[mask], v[mask], windspeed[mask])  # Plot a line colored by wind speed

    # Set some sensible axis limits
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    return fig, skew
예제 #3
0
def test_skewt_shade_cape_cin(test_profile):
    """Test shading CAPE and CIN on a SkewT plot."""
    p, t, tp = test_profile
    fig = plt.figure(figsize=(9, 9))
    skew = SkewT(fig)
    skew.plot(p, t, 'r')
    skew.plot(p, tp, 'k')
    skew.shade_cape(p, t, tp)
    skew.shade_cin(p, t, tp)
    return fig
예제 #4
0
def test_skewt_shade_cape_cin(test_profile):
    """Test shading CAPE and CIN on a SkewT plot."""
    p, t, tp = test_profile
    fig = plt.figure(figsize=(9, 9))
    skew = SkewT(fig)
    skew.plot(p, t, 'r')
    skew.plot(p, tp, 'k')
    skew.shade_cape(p, t, tp)
    skew.shade_cin(p, t, tp)
    skew.ax.set_xlim(-50, 50)
    return fig
예제 #5
0
def make_skewt():
    # Get the data
    date = request.args.get('date')
    time = request.args.get('time')
    region = request.args.get('region')
    station = request.args.get('station')
    date = datetime.strptime(date, '%Y%m%d')
    date = datetime(date.year, date.month, date.day, int(time))
    df = get_sounding_data(date, region, station)
    p = df['pressure'].values * units(df.units['pressure'])
    T = df['temperature'].values * units(df.units['temperature'])
    Td = df['dewpoint'].values * units(df.units['dewpoint'])
    u = df['u_wind'].values * units(df.units['u_wind'])
    v = df['v_wind'].values * units(df.units['v_wind'])

    # Make the Skew-T
    fig = plt.figure(figsize=(9, 9))
    add_metpy_logo(fig, 115, 100)
    skew = SkewT(fig, rotation=45)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, 'tab:red')
    skew.plot(p, Td, 'tab:green')
    skew.plot_barbs(p, u, v)
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    # Calculate LCL height and plot as black dot
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Calculate full parcel profile and add to plot as black line
    prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
    skew.plot(p, prof, 'k', linewidth=2)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p, T, prof)
    skew.shade_cape(p, T, prof)

    # An example of a slanted line at constant T -- in this case the 0
    # isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    canvas = FigureCanvas(fig)
    img = BytesIO()
    fig.savefig(img)
    img.seek(0)
    return send_file(img, mimetype='image/png')
예제 #6
0
    def plot_skewt(self, station_data):
        """
        :param adjusted_data: receives the post processed dataframe
        :param valid:
        :return:
        """

        # We will pull the data out of the example dataset into individual variables
        # and assign units.

        p = station_data['pressure'].values * units.hPa
        T = station_data['Temperature_isobaric'].values * units.degC
        Td = station_data['Dewpoint'].replace(np.nan,
                                              0.0000001).values * units.degC
        u = station_data['u-component_of_wind_isobaric'].values * \
            units('meters / second').to('knots')
        v = station_data['v-component_of_wind_isobaric'].values * \
            units('meters / second').to('knots')

        # Create a new figure. The dimensions here give a good aspect ratio.
        fig = plt.figure(figsize=(12, 9))
        skew = SkewT(fig, rotation=45)

        # Plot the data using normal plotting functions, in this case using
        # log scaling in Y, as dictated by the typical meteorological plot
        skew.plot(p, T, 'r')
        skew.plot(p, Td, 'g')
        skew.plot_barbs(p, u, v)
        skew.ax.set_ylim(1020, 100)
        skew.ax.set_xlim(-40, 60)

        # Calculate LCL height and plot as black dot
        lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
        skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

        # Calculate full parcel profile and add to plot as black line
        prof = mpcalc.parcel_profile(p, T[0], Td[0])
        skew.plot(p, prof, 'k', linewidth=2)

        # An example of a slanted line at constant T -- in this case the 0
        # isotherm
        skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

        # Add the relevant special lines
        skew.plot_dry_adiabats()
        skew.plot_moist_adiabats()
        skew.plot_mixing_lines()

        skew.shade_cape(p, T, prof)
        skew.shade_cin(p, T, prof)

        return skew
예제 #7
0
def core(p, T, Td, u, v, **kwargs):

    # Calculate the LCL
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])

    #print('LCL p, t:', int(lcl_pressure), int(lcl_temperature))

    # Calculate the parcel profile.
    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(8, 8))
    skew = SkewT(fig, rotation=45)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    #skew.plot(p, T, 'k-')
    skew.plot(p, T, 'r.-', ms=5, lw=2, label='mean T')
    skew.plot(p, Td, 'g.-', ms=5, lw=2, label='mean Td')
    skew.plot_barbs(p, u, v)
    skew.ax.set_ylim(1000, 180)
    skew.ax.set_xlim(-20, 40)

    # Plot LCL temperature as black dot
    skew.plot(lcl_pressure, lcl_temperature, 'k.', markerfacecolor='black')

    # Plot the parcel profile as a black line
    skew.plot(p, parcel_prof, 'k', linewidth=2)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p, T, parcel_prof)
    skew.shade_cape(p, T, parcel_prof)

    # Plot a zero degree isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats(lw=.5)
    skew.plot_moist_adiabats(lw=.5)
    skew.plot_mixing_lines(lw=.5)

    # Show the plot
    #plt.show()
    #skew.ax.set_title(time_str)
    plt.legend(loc='lower left')
    plt.title(kwargs.get('title'))
    fname = kwargs.get('saveto', 'profile.png')
    fig.savefig(fname)
    print(fname, 'saved.')
    plt.close()
예제 #8
0
파일: test_skewt.py 프로젝트: akrherz/MetPy
def test_skewt_shade_cape_cin(test_profile):
    """Test shading CAPE and CIN on a SkewT plot."""
    p, t, tp = test_profile

    with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
        fig = plt.figure(figsize=(9, 9))
        skew = SkewT(fig)
        skew.plot(p, t, 'r')
        skew.plot(p, tp, 'k')
        skew.shade_cape(p, t, tp)
        skew.shade_cin(p, t, tp)
        skew.ax.set_xlim(-50, 50)

    return fig
예제 #9
0
def test_skewt_shade_cape_cin(test_profile):
    """Test shading CAPE and CIN on a SkewT plot."""
    p, t, tp = test_profile

    with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
        fig = plt.figure(figsize=(9, 9))
        skew = SkewT(fig)
        skew.plot(p, t, 'r')
        skew.plot(p, tp, 'k')
        skew.shade_cape(p, t, tp)
        skew.shade_cin(p, t, tp)
        skew.ax.set_xlim(-50, 50)

    return fig
예제 #10
0
def plot_skewt(p, t, td, puv=None, u=None, v=None, title=None, outfile=None):

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(9, 9))
    skew = SkewT(fig, rotation=30)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, t, 'r', linewidth=2)
    skew.plot(p, td, 'g', linewidth=2)
    if u is not None and v is not None:
        skew.plot_barbs(puv, u, v)

    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    # Calculate the LCL
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], t[0], td[0])

    # Calculate the parcel profile.
    parcel_prof = mpcalc.parcel_profile(p, t[0], td[0]).to('degC')

    # Plot LCL temperature as black dot
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Plot the parcel profile as a black line
    skew.plot(p, parcel_prof, 'k--', linewidth=1)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p, t, parcel_prof)
    skew.shade_cape(p, t, parcel_prof)

    # Plot a zero degree isotherm
    #skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    if title is not None:
        plt.title(title)

    # Show the plot
    #plt.show()
    if outfile is None: outfile = 'skewt.png'
    fig.savefig(outfile, format='png')
예제 #11
0
def test_skewt_shade_cape_cin_no_limit(test_profile):
    """Test shading CIN without limits."""
    p, t, _, tp = test_profile

    with matplotlib.rc_context({'axes.autolimit_mode': 'data'}):
        fig = plt.figure(figsize=(9, 9))
        skew = SkewT(fig, aspect='auto')
        skew.plot(p, t, 'r')
        skew.plot(p, tp, 'k')
        skew.shade_cape(p, t, tp)
        skew.shade_cin(p, t, tp)
        skew.ax.set_xlim(-50, 50)
        skew.ax.set_ylim(1000, 100)

        # This works around the fact that newer pint versions default to degrees_Celsius
        skew.ax.set_xlabel('degC')

    return fig
예제 #12
0
def Skew_T_diagram(T, z, wv):
    """ Plot a Skew-T diagram. Credits @ MetPy: https://unidata.github.io/MetPy/latest/index.html """

    from metpy.plots import SkewT

    P = P_env(z) / 100
    wvs = wv_sat(T, z)

    Td = T_dew(wv, z)
    env = T_env(z)

    zLCL = np.argmin(abs(T - Td))
    P_LCL = P[:zLCL]
    Td = Td[:zLCL]

    fig = plt.figure(figsize=(11, 11))

    skew = SkewT(fig, rotation=45)
    skew.plot(P_LCL, Td, 'b', linewidth=3, label='T_dew')
    skew.plot(P, T, 'r', linewidth=3, label='T_parc')
    skew.plot(P, env, 'g', linewidth=3, label='T_env')
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()
    skew.ax.set_ylim(1010, 100)

    skew.plot(P[zLCL],
              T[zLCL],
              '.k',
              markersize=15,
              label='LCL = %.1f km' % np.round(z[zLCL] / 1000, 1))

    skew.shade_cin(P[zLCL:], env[zLCL:], T[zLCL:], label='Level above LFC')
    skew.shade_cape(P[zLCL:], env[zLCL:], T[zLCL:], label='CAPE')

    plt.legend()

    skew.ax.set_xlim(-30, 40)
    skew.ax.set_xlabel('Temperature [C]')
    skew.ax.set_ylabel('Pressure [hPa]')
    skew.ax.set_title('Skew-T diagram Essen Sounding')

    return plt.show()
예제 #13
0
skew.ax.set_ylim(1000, 100)
skew.ax.set_xlim(-40, 60)

# Calculate LCL height and plot as black dot. Because `p`'s first value is
# ~1000 mb and its last value is ~250 mb, the `0` index is selected for
# `p`, `T`, and `Td` to lift the parcel from the surface. If `p` was inverted,
# i.e. start from low value, 250 mb, to a high value, 1000 mb, the `-1` index
# should be selected.
lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

# Calculate full parcel profile and add to plot as black line
prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
skew.plot(p, prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, prof, Td)
skew.shade_cape(p, T, prof)

# An example of a slanted line at constant T -- in this case the 0
# isotherm
skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

# Add the relevant special lines
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()

# Show the plot
plt.show()
예제 #14
0
                                        labelcolor='brown')
                    skew.ax.tick_params(axis="y", labelsize=14, pad=0.5)

                    # Calculate full parcel profile and add to plot as black line
                    prof_0 = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
                    skew.plot(p, prof_0, 'k', linewidth=1.5)

                    # Shade areas of CAPE and CIN
                    '''
                    Calculate the convective available potential energy (CAPE) and convective inhibition (CIN) 
                    of a given upper air profile and most unstable parcel path. 
                    CIN is integrated between the surface and LFC, 
                    CAPE is integrated between the LFC and EL (or top of sounding). 
                    Intersection points of the measured temperature profile and parcel profile are linearly interpolated.
                    '''
                    skew.shade_cin(p, T, prof_0)
                    skew.shade_cape(p, T, prof_0)

                    # Calculate LCL height and plot as black dot
                    lcl_pressure, lcl_temperature = mpcalc.lcl(
                        p[0], T[0], Td[0])
                    skew.plot(lcl_pressure,
                              lcl_temperature,
                              'ko',
                              markersize=8,
                              fillstyle='none',
                              label='LCL')

                    # Calculate LCF height and plot as purple dot
                    LCF_pressure, LCF_temperature = mpcalc.lfc(
                        p, T, Td, prof_0)
예제 #15
0
def skewt_plots(dt, station, p, T, Td, u, v, outdir, idxij, utch, z):
    # skewt_plots(dt,station,p,T,Td,u,v,outdir,idxij,utch)
    # Function to make the graphic ploting of the sounding.
    # ---INPUTS:
    # dt = "2016-10-26 13h CET (12 UTC)" # string of valid time
    # station = "Piedtahita" station name
    # p pressure colmn on coordinates
    # T temp colmn on coordinates
    # Td dew point colmn on coordinates
    # u,v wind vectors colmn on coordinates
    # outdir='plots/' #output directory
    # idxij matrix coordinates of the sounding
    # utch="1200" #string of utc hour for filename
    # z geopotential height
    # ---OUTPUTS:
    # plot in outdir

    p = p.interp(south_north=idxij[1], west_east=idxij[0])
    lon = p.XLONG.values
    lat = p.XLAT.values
    dx = p.projection.dx
    dy = p.projection.dy
    p = p.values
    T = T.interp(south_north=idxij[1], west_east=idxij[0]).values
    Td = Td.interp(south_north=idxij[1], west_east=idxij[0]).values
    u = u.interp(south_north=idxij[1], west_east=idxij[0]).values
    v = v.interp(south_north=idxij[1], west_east=idxij[0]).values
    z = z.interp(south_north=idxij[1], west_east=idxij[0]).values
    ######################################################################
    # Make Skew-T Plot
    # ----------------
    # The code below makes a basic skew-T plot using the MetPy plot module
    # that contains a SkewT class.

    # Change default to be better for skew-T
    fig = plt.figure(figsize=(11, 9))
    plt.rcParams.update({'font.size': 12})
    # Initiate the skew-T plot type from MetPy class loaded earlier
    skew = SkewT(fig, rotation=45)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, 'r')
    skew.plot(p, Td, 'g')
    skew.plot_barbs(p[::3], u[::3], v[::3], y_clip_radius=0.03)

    # Set some appropriate axes limits for x and y
    #skew.ax.set_xlim(-30, 40)
    skew.ax.set_ylim(1020, 200)
    skew.ax.set_ylabel('Pressure [hPa]')
    skew.ax.set_xlabel('Temperature [ºC]')

    heights = np.array([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]) * units.km
    std_pressures = mpcalc.height_to_pressure_std(heights)
    for height_tick, p_tick in zip(heights, std_pressures):
        trans, _, _ = skew.ax.get_yaxis_text1_transform(0)
        skew.ax.text(0.02,
                     p_tick,
                     '---{:~d}'.format(height_tick),
                     transform=trans)

    # Calculate LCL height and plot as black dot. Because `p`'s first value is
    # ~1000 mb and its last value is ~250 mb, the `0` index is selected for
    # `p`, `T`, and `Td` to lift the parcel from the surface. If `p` was inverted,
    # i.e. start from low value, 250 mb, to a high value, 1000 mb, the `-1` index
    # should be selected.
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0] * units.hPa,
                                               T[0] * units.degC,
                                               Td[0] * units.degC)
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Calculate full parcel profile and add to plot as black line
    prof = mpcalc.parcel_profile(p * units.hPa, T[0] * units.degC,
                                 Td[0] * units.degC).to('degC')
    skew.plot(p, prof, 'k', linewidth=2)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p * units.hPa, T * units.degC, prof)
    skew.shade_cape(p * units.hPa, T * units.degC, prof)

    # An example of a slanted line at constant T -- in this case the 0
    # isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines to plot throughout the figure
    skew.plot_dry_adiabats(t0=np.arange(233, 533, 10) * units.K,
                           alpha=0.6,
                           color='orangered')
    skew.plot_moist_adiabats(t0=np.arange(233, 400, 5) * units.K,
                             alpha=0.6,
                             color='tab:green')
    #skew.plot_mixing_lines(p=np.arange(1000, 99, -20) * units.hPa,
    #                       linestyle='dotted', color='tab:blue')

    # Add some descriptive titles
    plt.title('Sounding ' + station + '\n(' + str('{0:.6f}'.format(lat)) +
              ' , ' + str('{0:.6f}'.format(lon)) + ') ',
              loc='left')
    plt.title('Valid for: ' + dt + '\n by RASPURI  ', loc='right')
    UTC_time = time.gmtime()
    plt.figtext(
        0.99,
        0.01,
        time.strftime('Computed on %d/%m/%y %H:%M:%S UTC \n', UTC_time) +
        'dx: ' + str(dx) + 'm dy: ' + str(dy) + 'm ',
        horizontalalignment='right',
        fontsize=10)
    #plt.figtext(0.01, 0.01, 'RASPURI by Oriol Cevrelló ', horizontalalignment='right')
    plt.tight_layout()
    filename = outdir + station + '_' + utch + '.png'
    #plt.show()
    plt.savefig(filename)
    plt.close()
예제 #16
0
# Plot the data using normal plotting functions, in this case using
# log scaling in Y, as dictated by the typical meteorological plot
skew.plot(p, T, 'r')
skew.plot(p, Td, 'g')
skew.plot_barbs(p, u, v)
skew.ax.set_ylim(1000, 100)
skew.ax.set_xlim(-40, 60)

# Plot LCL temperature as black dot
skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

# Plot the parcel profile as a black line
skew.plot(p, parcel_prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, parcel_prof)
skew.shade_cape(p, T, parcel_prof)

# Plot a zero degree isotherm
skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

# Add the relevant special lines
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()

# Show the plot
plt.show()

##########################################################################
# Adding a Hodograph
예제 #17
0
def plot_upper_air(station='11035', date=False):
    '''
    -----------------------------
    Default use of plot_upper_air:

    This will plot a SkewT sounding for station '11035' (Wien Hohe Warte)
    plot_upper_air(station='11035', date=False)
    '''
    # sns.set(rc={'axes.facecolor':'#343837', 'figure.facecolor':'#343837',
    #  'grid.linestyle':'','axes.labelcolor':'#04d8b2','text.color':'#04d8b2',
    #  'xtick.color':'#04d8b2','ytick.color':'#04d8b2'})
    # Get time in UTC
    station = str(station)
    if date is False:
        now = datetime.utcnow()
        # If morning then 0z sounding, otherwise 12z
        if now.hour < 12:
            hour = 0
        else:
            hour = 12
        date = datetime(now.year, now.month, now.day, hour)
        datestr = date.strftime('%Hz %Y-%m-%d')
        print('{}'.format(date))
    else:
        year = int(input('Please specify the year: '))
        month = int(input('Please specify the month: '))
        day = int(input('Please specify the day: '))
        hour = int(input('Please specify the hour: '))
        if hour < 12:
            hour = 0
        else:
            hour = 12
        date = datetime(year, month, day, hour)
        datestr = date.strftime('%Hz %Y-%m-%d')
        print('You entered {}'.format(date))

    # This requests the data 11035 is
    df = WyomingUpperAir.request_data(date, station)

    # Create single variables wih the right units
    p = df['pressure'].values * units.hPa
    T = df['temperature'].values * units.degC
    Td = df['dewpoint'].values * units.degC
    wind_speed = df['speed'].values * units.knots
    wind_dir = df['direction'].values * units.degrees

    wind_speed_6k = df['speed'][df.height <= 6000].values * units.knots
    wind_dir_6k = df['direction'][df.height <= 6000].values * units.degrees

    u, v = mpcalc.get_wind_components(wind_speed, wind_dir)
    u6, v6 = mpcalc.get_wind_components(wind_speed_6k, wind_dir_6k)

    # Calculate the LCL
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    print(lcl_pressure, lcl_temperature)
    # Calculate the parcel profile.
    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
    cape, cin = mpcalc.cape_cin(p, T, Td, parcel_prof)

    #############################
    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(9, 9))
    gs = gridspec.GridSpec(3, 3)
    skew = SkewT(fig, rotation=45, subplot=gs[:, :2])

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, 'r')
    skew.plot(p, Td, 'g')
    skew.plot_barbs(p, u, v)
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-45, 40)

    # Plot LCL as black dot
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Plot the parcel profile as a black line
    skew.plot(p, parcel_prof, 'k', linewidth=2)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p, T, parcel_prof)
    skew.shade_cape(p, T, parcel_prof)

    # Plot a zero degree isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)
    skew.ax.set_title('Station: ' + str(station) + '\n' + datestr)  # set title
    skew.ax.set_xlabel('Temperature (C)')
    skew.ax.set_ylabel('Pressure (hPa)')

    # Add the relevant special lines
    skew.plot_dry_adiabats(linewidth=0.7)
    skew.plot_moist_adiabats(linewidth=0.7)
    skew.plot_mixing_lines(linewidth=0.7)

    # Create a hodograph
    # Create an inset axes object that is 40% width and height of the
    # figure and put it in the upper right hand corner.
    # ax_hod = inset_axes(skew.ax, '40%', '40%', loc=1)
    ax = fig.add_subplot(gs[0, -1])
    h = Hodograph(ax, component_range=60.)
    h.add_grid(increment=20)
    # Plot a line colored by windspeed
    h.plot_colormapped(u6, v6, wind_speed_6k)

    # add another subplot for the text of the indices
    # ax_t = fig.add_subplot(gs[1:,2])
    skew2 = SkewT(fig, rotation=0, subplot=gs[1:, 2])
    skew2.plot(p, T, 'r')
    skew2.plot(p, Td, 'g')
    # skew2.plot_barbs(p, u, v)
    skew2.ax.set_ylim(1000, 700)
    skew2.ax.set_xlim(-30, 10)

    # Show the plot
    plt.show()

    return cape
예제 #18
0
skew.ax.set_ylim(1000, 100)
skew.ax.set_xlim(-40, 60)

# Calculate LCL height and plot as black dot. Because `p`'s first value is
# ~1000 mb and its last value is ~250 mb, the `0` index is selected for
# `p`, `T`, and `Td` to lift the parcel from the surface. If `p` was inverted,
# i.e. start from low value, 250 mb, to a high value, 1000 mb, the `-1` index
# should be selected.
lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

# Calculate full parcel profile and add to plot as black line
prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
skew.plot(p, prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, prof)
skew.shade_cape(p, T, prof)

# An example of a slanted line at constant T -- in this case the 0
# isotherm
skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

# Add the relevant special lines
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()

# Show the plot
plt.show()
예제 #19
0
def cape(filelist,storm,track,show):
    #Sort filelist.
    filelist=np.sort(filelist)

    # Get sampling periods (this will be a dictionary). See the toolbox
    print('Retrieving sampling periods')
    sampleperiods=getsamplingperiods(filelist,3.)

    # Iterate over all sampling periods.
    for sampindex,periodskey in enumerate(sampleperiods):

        #Allocate starting (stdt) and ending date (endt). Remeber dt is the convetional short-name for date.
        stdt=periodskey
        endt=sampleperiods[periodskey]

        # Define sampling period string
        period=str(stdt.hour)+'_'+str(stdt.day)+'-'+str(endt.hour)+'_'+str(endt.day)

        # Create new-empty lists.
        lats=[]
        lons=[]
        xs=[]
        ys=[]
        capes=[]
        cins=[]
	
        distfig = plt.figure(figsize=(13, 9))
        ax=distfig.add_subplot(111)
        print('start filelist loop')
        # Iterate over all files.
        for filename in filelist:



            # Select end-name of file by inspecting filename string. Notice how filename can change how file is read.
            if 'radazm' in filename.split('/')[-1] or 'eol' in filename.split('/')[-1]:
                end='radazm'
            else:
                end='avp'
            # Obtain properties of file, i.e., launch time and location into a dictionary (dicc).
            dicc=findproperties(filename,end)

            # Condition to see if current file is in sampling period.
            # Notice how if structure is constructed, condition finds times outside of sampling period and
            # if found outside the sampling period, continue to next file.
            if dicc['Launch Time']<stdt or dicc['Launch Time'] > endt:
                continue

            nump=np.genfromtxt(filename,skip_header=16,skip_footer=0)
            temperature=clean1(nump[:,5])
            pressure=clean1(nump[:,4])
            Height=clean1(nump[:,13])
            if np.nanmax(Height)<3500:
                continue
            #Clean for cape
            RelH=clean1(nump[:,7])
            lon=clean1(nump[:,14])
            lat=clean1(nump[:,15])
            lon=clean1(lon)
            lat=clean1(lat)
            mlon=np.nanmean(lon)
            mlat=np.nanmean(lat)
            RH=RelH/100
            T,P,rh,dz=cleanforcape(temperature,pressure,RH,Height)

            #Metpy set-up
            T=np.flip(T,0)
            rh=np.flip(rh,0)
            p=np.flip(P,0)
            dz=np.flip(dz,0)
            p=p*units.hPa
            T=T*units.celsius


            mixing=rh*mpcalc.saturation_mixing_ratio(p,T)
            epsilon=0.6219800858985514
            Tv=mpcalc.virtual_temperature(T, mixing,
                                      molecular_weight_ratio=epsilon)
            dwpoint=mpcalc.dewpoint_rh(T, rh)

            blh_indx=np.where(dz<500)
            try:
                parcelprofile=mpcalc.parcel_profile(p,np.nanmean(T[blh_indx])*units.celsius,mpcalc.dewpoint_rh(np.nanmean(T[blh_indx])*units.celsius, np.nanmean(rh[blh_indx]))).to('degC')
                Tv_parcelprofile=mpcalc.virtual_temperature(parcelprofile, mixing,
                                          molecular_weight_ratio=epsilon)
                cape,cin=cape_cin(p,Tv,dwpoint,Tv_parcelprofile,dz,T)
            except:
                continue

            plotskewT=True
            if plotskewT==True:

                os.system('mkdir figs/skewt')
                fig = plt.figure(figsize=(9, 9))
                skew = SkewT(fig, rotation=45)
                skew.ax.set_ylim(1000, 100)
                skew.ax.set_xlim(-40, 60)

                skew.plot(p, dwpoint, 'g',label=r'$T_{dp}$')
                skew.plot(p, Tv, 'r',label=r'$T_v$')
                plt.text(-120,120,str(np.around(cape,2)),fontsize=14,fontweight='bold')

                # Plot the data using normal plotting functions, in this case using
                # log scaling in Y, as dictated by the typical meteorological plot
                skew.plot(p,Tv_parcelprofile,'k',label=r'$T_{v env}$')
                skew.shade_cin(p, T, parcelprofile,label='CIN')
                skew.shade_cape(p, Tv, Tv_parcelprofile,label='CAPE')
                skew.plot_dry_adiabats()
                skew.plot_moist_adiabats()

                plt.legend()
                plt.title(storm + ' on' + period,fontsize=14)
                plt.savefig('figs/skewt/'+storm+str(dicc['Launch Time'].time())+'.png')
                #plt.show()
                plt.close()

            r,theta=cart_to_cylindr(mlon,mlat,track,dicc['Launch Time'])
            if not(np.isnan(r)) and not(np.isnan(theta)) and not(np.isnan(cape.magnitude)):
                xs.append(r*np.cos(theta))
                ys.append(r*np.sin(theta))
                capes.append(cape.magnitude)
                cins.append(cin)


            cs=ax.scatter(xs,ys,c=np.asarray(capes),cmap='jet')
            for i,xi in enumerate(xs):
                ax.text(xi,ys[i]+10,str(np.around(capes[i],1)))
        plt.colorbar(cs)
        ax.scatter(0,0,marker='v',s=100,color='black')
        ax.grid()
        ax.set_xlabel('X distance [km]')
        ax.set_ylabel('Y distance [km]')
        ax.set_title('CAPE distribution for '+storm+' on '+period,fontsize=14)
        distfig.savefig('figs/cape'+storm+period+'.png')
        if show:
            plt.show()
예제 #20
0
    def plot_skewt(self):
        """
        :param adjusted_data: receives the post processed dataframe
        :param valid:
        :return:
        """
        for area in self.airports:
            for airport in self.airports[area]:
                lon = self.airports[area][airport]['lon']
                lat = self.airports[area][airport]['lat']
                pressure_levels = self.levels * units.hPa
                tair = list(
                    self.create_profile_variable(self.tair, lat,
                                                 lon).values()) * units.degC
                dewp = list(
                    self.create_profile_variable(self.dewp, lat,
                                                 lon).values()) * units.degC
                u_wnd = list(self.create_profile_variable(self.u_wnd, lat, lon).values()) * \
                        units('meters / second').to('knots')
                v_wnd = list(self.create_profile_variable(self.v_wnd, lat, lon).values()) * \
                        units('meters / second').to('knots')

                # Create a new figure. The dimensions here give a good aspect ratio.
                fig = plt.figure(figsize=(12, 9))
                skew = SkewT(fig, rotation=45)

                # Plot the data using normal plotting functions, in this case using
                # log scaling in Y, as dictated by the typical meteorological plot
                skew.plot(pressure_levels, tair, 'r')
                skew.plot(pressure_levels, dewp, 'g')
                skew.plot_barbs(pressure_levels, u_wnd, v_wnd)
                skew.ax.set_ylim(1020, 100)
                skew.ax.set_xlim(-40, 60)

                # Calculate LCL height and plot as black dot
                lcl_pressure, lcl_temperature = mpcalc.lcl(
                    pressure_levels[0], tair[0], dewp[0])
                skew.plot(lcl_pressure,
                          lcl_temperature,
                          'ko',
                          markerfacecolor='black')

                # Calculate full parcel profile and add to plot as black line
                prof = mpcalc.parcel_profile(pressure_levels, tair[0], dewp[0])
                skew.plot(pressure_levels, prof, 'k', linewidth=2)

                # An example of a slanted line at constant T -- in this case the 0
                # isotherm
                skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

                # Add the relevant special lines
                skew.plot_dry_adiabats()
                skew.plot_moist_adiabats()
                skew.plot_mixing_lines()

                skew.shade_cape(pressure_levels, tair, prof)
                skew.shade_cin(pressure_levels, tair, prof)
                plt.title(
                    f'Perfil vertical (GFS) de {airport} valido para {self.time_stamp}',
                    fontsize=16,
                    ha='center')
                sounding_output_path = f'{self.output_path}/{area}/{airport}'
                Path(sounding_output_path).mkdir(parents=True, exist_ok=True)
                plt.savefig(
                    f'{sounding_output_path}/sounding_{airport}_{self.time_step:02d}.jpg'
                )

        return skew
예제 #21
0
def plot_soundings(fig,ax,temp,rh,centerlat,centerlon,domainsize,cape):
    '''
    This function will plot a bunch of little soundings onto a matplotlib fig,ax.

    temp is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change the ylimits for other datasets)

    rh is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change )

    centerlat and centerlon are the coordinates around which you want your map
    to be centered. both are floats or integers and are in degrees of latitude
    and degrees of longitude west (i.e. 70W would be input as positive 70 here)

    domainsize is a string either 'local' for ~WFO-size domains or 'regional' for
    NE/SE/Mid-Atlantic-size domains (12 deg lat by 15 deg lon). More will be added soon.

    cape is a boolean to indicate whether you want to overlay parcel paths and
    shade CAPE/CIN on soundings with >100 J/kg of CAPE (this value can be changed)

    note that this function doesn't "return" anything but if you just call it and
    provide the right arguments, it works.

    for example:
        import soundingmaps as smap
        ...
        smap.plot_soundings(fig,ax1,data['temperature'],data['rh'],30.5,87.5,'local',cape=True)

    '''
    r=5
    if domainsize=='local':
        init_lat_delt = 1.625
        init_lon_delt = 0.45
        lat_delts = [.2,.7,1.2,1.75,2.25,2.8]
        londelt = 0.76
        startlon = centerlon-2+0.45

    elif domainsize=='regional':
        init_lat_delt = 6
        init_lon_delt = 1.6
        lat_delts = [0.6,2.5,4.5,6.4,8.4,10.25]
        londelt = 2.9
        startlon = centerlon-7.5+1.6

    startlat = centerlat-init_lat_delt
    startlon = centerlon-2+0.45

    sound_lats=[]
    sound_lons=[]
    for i in range(0,6):
        lats = startlat+lat_delts[i]
        sound_lats.append(lats)

    for i in range(0,r):
        lons = -startlon-(londelt*i)
        sound_lons.append(lons)

    plot_elevs=[0.2,0.3,0.4,0.5,0.6,0.7]

    dashed_red_line = lines.Line2D([], [], linestyle='solid', color='r', label='Temperature')
    dashed_purple_line = lines.Line2D([],[],linestyle='dashed',color='purple',label='0C Isotherm')
    dashed_green_line = lines.Line2D([], [], linestyle='solid', color='g', label='Dew Point')
    grey_line = lines.Line2D([], [], color='darkgray', label='MSLP (hPa)')
    blue_line = lines.Line2D([], [], color='b',label='2m 0C Isotherm')
    pink_line = lines.Line2D([], [], color='fuchsia',label='Surface-Based Parcel Path')
    red = mpatches.Patch(color='tab:red',label='CAPE')
    blue = mpatches.Patch(color='tab:blue',label='CIN')

    if cape==True:
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k==0:
                s=1
            else:
                s=0

            for i in range(s,r):
                sound_pres = temp.lev
                soundlon = -(startlon+(londelt*i))
                sound_temps = temp.interp(lat=soundlat,lon=soundlon)-273.15
                sound_rh = rh.interp(lat=soundlat,lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(sound_temps.data*units.degC,sound_rh.data*units.percent)
                skew = SkewT(fig=fig,rect=(0.75-(0.15*i),plot_elev,.15,.1))

                parcel_prof = mpcalc.parcel_profile(sound_pres,sound_temps[0].data*units.degC,sound_dp[0])
                cape = mpcalc.cape_cin(sound_pres,sound_temps.data*units.degC,sound_dp,parcel_prof)
                capeout = int(cape[0].m)
                cinout = int(cape[1].m)

                skew.plot(sound_pres,sound_dp,'g',linewidth=3)
                skew.plot(sound_pres,sound_temps,'r',linewidth=3)

                if capeout >100:
                    # Shade areas of CAPE and CIN
                    print(sound_temps)
                    print(parcel_prof)
                    skew.shade_cin(sound_pres, sound_temps.data*units.degC, parcel_prof)
                    skew.shade_cape(sound_pres, sound_temps.data*units.degC, parcel_prof)
                    skew.plot(sound_pres,parcel_prof,color='fuchsia',linewidth=1)

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000,300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[dashed_red_line,dashed_green_line,dashed_purple_line,pink_line,red,blue],title='Sounding Legend',loc=4,framealpha=1)

    else:
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k==0:
                s=1
            else:
                s=0

            for i in range(s,r):
                soundlon = -(startlon+(londelt*i))
                sound_pres = temp.lev
                sound_temps = temp.interp(lat=soundlat,lon=soundlon)-273.15
                sound_rh = rh.interp(lat=soundlat,lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(sound_temps.data*units.degC,sound_rh.data*units.percent)
                skew = SkewT(fig=fig,rect=(0.75-(0.15*i),plot_elev,.15,.1))
                skew.plot(sound_pres,sound_dp,'g',linewidth=3)
                skew.plot(sound_pres,sound_temps,'r',linewidth=3)
                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000,300))
                skew.ax.axis('off')
        leg = ax.legend(handles=[dashed_red_line,dashed_green_line,dashed_purple_line],title='Sounding Legend',loc=4,framealpha=1)
예제 #22
0
def main():
    args = get_args()
    setup_logging(args['verbose'])

    # Define input file
    file = args['inputfile']
    output = args['outputfile']

    ds = xr.open_dataset(file)

    ds_sel = ds.isel({'sounding': 0})
    ds_sel = ds_sel.sortby(ds_sel.pressure, ascending=False)

    p = ds_sel.pressure.values
    T = ds_sel.temperature.values
    Td = ds_sel.dewPoint.values
    wind_speed = ds_sel.windSpeed.values
    wind_dir = ds_sel.windDirection.values

    # Filter nans
    idx = np.where((np.isnan(T) + np.isnan(Td) + np.isnan(p) +
                    np.isnan(wind_speed) + np.isnan(wind_dir)) == False, True,
                   False)
    p = p[idx]
    T = T[idx]
    Td = Td[idx]
    wind_speed = wind_speed[idx]
    wind_dir = wind_dir[idx]

    # Add units
    p = p * units.hPa
    T = T * units.degC
    Td = Td * units.degC
    wind_speed = wind_speed * (units.meter / units.second)
    wind_dir = wind_dir * units.degrees

    u, v = mpcalc.wind_components(wind_speed, wind_dir)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])

    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(9, 10))
    skew = SkewT(fig, rotation=30)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, 'r')
    skew.plot(p, Td, 'g')
    # Plot only specific barbs to increase visibility
    pressure_levels_barbs = np.logspace(0.1, 1, 50) * 100

    def find_nearest(array, value):
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return array[idx]

    # Search for levels by providing pressures
    # (levels is the coordinate not pressure)
    pres_vals = ds_sel.pressure.values[idx]
    closest_pressure_levels = np.unique(
        [find_nearest(pres_vals, p_) for p_ in pressure_levels_barbs])
    _, closest_pressure_levels_idx, _ = np.intersect1d(pres_vals,
                                                       closest_pressure_levels,
                                                       return_indices=True)

    p_barbs = ds_sel.pressure.isel({
        'levels': closest_pressure_levels_idx
    }).values * units.hPa
    wind_speed_barbs = ds_sel.windSpeed.isel({
        'levels':
        closest_pressure_levels_idx
    }).values * (units.meter / units.second)
    wind_dir_barbs = ds_sel.windDirection.isel({
        'levels':
        closest_pressure_levels_idx
    }).values * units.degrees
    u_barbs, v_barbs = mpcalc.wind_components(wind_speed_barbs, wind_dir_barbs)

    # Find nans in pressure
    # p_non_nan_idx = np.where(~np.isnan(pres_vals))
    skew.plot_barbs(p_barbs, u_barbs, v_barbs, xloc=1.06)

    # set axes limits:
    skew.ax.set_ylim(1020, 100)
    skew.ax.set_xlim(-50, 40)

    # Plot LCL as black dot
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Plot the parcel profile as a black line
    skew.plot(pres_vals, parcel_prof, 'k', linewidth=1.6)

    # Shade areas of CAPE and CIN
    skew.shade_cin(pres_vals, T, parcel_prof)
    skew.shade_cape(pres_vals, T, parcel_prof)

    # Plot a zero degree isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    # Create a hodograph
    # Create an inset axes object that is 40% width and height of the
    # figure and put it in the upper right hand corner.
    ax_hod = inset_axes(skew.ax, '35%', '35%', loc=1)
    h = Hodograph(ax_hod, component_range=75.)
    h.add_grid(increment=20)
    h.plot_colormapped(u, v, wind_speed)  # Plot a line colored by wind speed

    # Set title
    sounding_name = ds_sel.sounding.values
    sounding_name_str = str(sounding_name.astype('str'))
    skew.ax.set_title('{sounding}'.format(sounding=sounding_name_str))

    if output is None:
        output = str(os.path.basename(file).split('.')[0]) + '.pdf'
    logging.info('Write output to {}'.format(output))
    plt.savefig(output)
예제 #23
0
def draw_sta_skewT(p=None,
                   T=None,
                   Td=None,
                   wind_speed=None,
                   wind_dir=None,
                   u=None,
                   v=None,
                   fcst_info=None,
                   output_dir=None):
    fig = plt.figure(figsize=(9, 9))
    skew = SkewT(fig, rotation=45)

    plt.rcParams['font.sans-serif'] = ['SimHei']  # 步骤一(替换sans-serif字体)
    plt.rcParams['axes.unicode_minus'] = False  # 步骤二(解决坐标轴负数的负号显示问题)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot.
    skew.plot(p, T, 'r')
    skew.plot(p, Td, 'g')
    skew.plot_barbs(p, u, v)
    skew.ax.set_ylim(1000, 100)
    skew.ax.set_xlim(-40, 60)

    # Calculate LCL height and plot as black dot. Because `p`'s first value is
    # ~1000 mb and its last value is ~250 mb, the `0` index is selected for
    # `p`, `T`, and `Td` to lift the parcel from the surface. If `p` was inverted,
    # i.e. start from low value, 250 mb, to a high value, 1000 mb, the `-1` index
    # should be selected.
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

    # Calculate full parcel profile and add to plot as black line
    prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
    skew.plot(p, prof, 'k', linewidth=2)

    # Shade areas of CAPE and CIN
    skew.shade_cin(p, T, prof)
    skew.shade_cape(p, T, prof)

    # An example of a slanted line at constant T -- in this case the 0
    # isotherm
    skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    #forecast information
    bax = plt.axes([0.12, 0.88, .25, .07], facecolor='#FFFFFFCC')
    bax.axis('off')
    bax.axis([0, 10, 0, 10])

    initTime = pd.to_datetime(str(
        fcst_info['forecast_reference_time'].values)).replace(
            tzinfo=None).to_pydatetime()
    if (sys.platform[0:3] == 'lin'):
        locale.setlocale(locale.LC_CTYPE, 'zh_CN.utf8')
    if (sys.platform[0:3] == 'win'):
        locale.setlocale(locale.LC_CTYPE, 'chinese')
    plt.text(2.5, 7.5, '起报时间: ' + initTime.strftime("%Y年%m月%d日%H时"), size=11)
    plt.text(2.5,
             5.0,
             '[' + str(fcst_info.attrs['model']) + '] ' +
             str(int(fcst_info['forecast_period'].values[0])) + '小时预报探空',
             size=11)
    plt.text(2.5,
             2.5,
             '预报点: ' + str(fcst_info.attrs['points']['lon']) + ', ' +
             str(fcst_info.attrs['points']['lat']),
             size=11)
    plt.text(2.5, 0.5, 'www.nmc.cn', size=11)
    utl.add_logo_extra_in_axes(pos=[0.1, 0.88, .07, .07],
                               which='nmc',
                               size='Xlarge')

    # Show the plot
    if (output_dir != None):
        plt.savefig(
            output_dir + '时间剖面产品_起报时间_' +
            str(fcst_info['forecast_reference_time'].values)[0:13] + '_预报时效_' +
            str(int(fcst_info.attrs['forecast_period'].values)) + '.png',
            dpi=200,
            bbox_inches='tight')
    else:
        plt.show()
예제 #24
0
def skewt_plot(p,
               tc,
               tdc,
               t0,
               date,
               u=None,
               v=None,
               fout='sounding.png',
               latlon='',
               title='',
               show=False):
    """
   h: heights
   p: pressure
   tc: Temperature [C]
   tdc: Dew point [C]
   date: date of the forecast
   u,v: u,v wind components
   adapted from:
   https://geocat-examples.readthedocs.io/en/latest/gallery/Skew-T/NCL_skewt_3_2.html#sphx-glr-gallery-skew-t-ncl-skewt-3-2-py
   """
    Pmax = 150  # XXX upper limit
    print('Checking units')
    if p.attrs['units'] != 'hPa':
        print('P wrong units')
        exit()
    if tc.attrs['units'] != 'degC':
        print('Tc wrong units')
        exit()
    if tdc.attrs['units'] != 'degC':
        print('Tdc wrong units')
        exit()
    if t0.attrs['units'] != 'degC':
        print('T0 wrong units')
        exit()
    if type(u) != type(None) and type(v) != type(None):
        if u.attrs['units'] != 'm s-1':
            print('Wind wrong units')
            exit()
    LG.info('Inside skewt plot')
    p = p.values
    tc = tc.values
    tdc = tdc.values
    t0 = t0.mean().values
    u = u.values * 3.6  # km/h
    v = v.values * 3.6  # km/h
    # Grid plot
    LG.info('creating figure')
    fig = plt.figure(figsize=(11, 12))
    LG.info('created figure')
    LG.info('creating axis')
    gs = gridspec.GridSpec(1, 2, width_ratios=[4, 1])
    fig.subplots_adjust(wspace=0., hspace=0.)
    # ax1 = plt.subplot(gs[1:-1,0])
    # Adding the "rotation" kwarg will over-ride the default MetPy rotation of
    # 30 degrees for the 45 degree default found in NCL Skew-T plots
    LG.info('created axis')
    LG.info('Creatin SkewT')
    skew = SkewT(fig, rotation=45, subplot=gs[0, 0])
    ax = skew.ax
    LG.info('Created SkewT')

    if len(latlon) > 0:
        ax.text(0,
                1,
                latlon,
                va='top',
                ha='left',
                color='k',
                fontsize=12,
                bbox=dict(boxstyle="round", ec=None, fc=(1., 1., 1., 0.9)),
                zorder=100,
                transform=ax.transAxes)
    # Plot the data, T and Tdew vs pressure
    skew.plot(p, tc, 'C3')
    skew.plot(p, tdc, 'C0')
    LG.info('plotted dew point and sounding')

    # LCL
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0] * units.hPa,
                                               t0 * units.degC,
                                               tdc[0] * units.degC)
    skew.plot(lcl_pressure, lcl_temperature, 'k.')

    # Calculate the parcel profile  #XXX units workaround
    parcel_prof = mpcalc.parcel_profile(p * units.hPa, t0 * units.degC,
                                        tdc[0] * units.degC).to('degC')
    # Plot cloud base
    ind_cross = np.argmin(np.abs(parcel_prof.magnitude - tc))
    p_base = np.max([lcl_pressure.magnitude, p[ind_cross]])
    t_base = np.max([lcl_temperature.magnitude, tc[ind_cross]])
    m_base = mpcalc.pressure_to_height_std(np.array(p_base) * units.hPa)
    m_base = m_base.to('m').magnitude
    skew.ax.axhline(p_base, color=(0.5, 0.5, 0.5), ls='--')
    skew.plot(p_base, t_base, 'C3o', zorder=100)
    skew.ax.text(t_base, p_base, f'{m_base:.0f}m', ha='left')

    # Plot the parcel profile as a black line
    skew.plot(p, parcel_prof, 'k', linewidth=1)
    LG.info('plotted parcel profile')

    # shade CAPE and CIN
    skew.shade_cape(p * units.hPa, tc * units.degC, parcel_prof)
    skew.shade_cin(p * units.hPa, tc * units.degC, parcel_prof,
                   tdc * units.degC)
    LG.info('plotted CAPE and CIN')

    if type(u) != type(None) and type(v) != type(None):
        LG.info('Plotting wind')
        ax2 = plt.subplot(gs[0, 1], sharey=ax, zorder=-1)
        # ax2.yaxis.set_visible(False)
        ax2.yaxis.tick_right()
        # ax2.xaxis.tick_top()
        wspd = np.sqrt(u * u + v * v)
        ax2.scatter(wspd, p, c=p, cmap=HEIGHTS, zorder=10)
        gnd = mpcalc.pressure_to_height_std(np.array(p[0]) * units.hPa)
        gnd = gnd.to('m')
        # Ground
        ax2.axhline(p[0], c='k', ls='--')
        ax2.text(56,
                 p[0],
                 f'{int(gnd.magnitude)}m',
                 horizontalalignment='right')
        # Techo
        ax2.axhline(p_base, c=(0.5, 0.5, 0.5), ls='--')
        ### Background colors ##
        #for i,c in enumerate(WindSpeed.colors):
        #   rect = Rectangle((i*4, 150), 4, 900,  color=c, alpha=0.5,zorder=-1)
        #   ax2.add_patch(rect)
        #########################
        ax2.set_xlim(0, 56)
        ax2.set_xlabel('Wspeed (km/h)')
        ax2.grid()

        def p2h(x):
            """
         x in hPa
         """
            y = mpcalc.pressure_to_height_std(np.array(x) * units.hPa)
            # y = y.metpy.convert_units('m')
            y = y.to('m')
            return y.magnitude

        def h2p(x):
            """
         x in m
         """
            # x = x.values
            y = mpcalc.height_to_pressure_std(np.array(x) * units.m)
            # y = y.metpy.convert_units('hPa')
            y = y.to('hPa')
            return y.magnitude

        # print('------')
        # print(p[0])
        # print('---')
        # print(p2h(p[0]))
        # print('---')
        # print(h2p(p2h(p[0])))
        # print('------')
        # exit()

        ax2y = ax2.secondary_yaxis(1.02, functions=(p2h, h2p))
        ax2y.set_ylabel('height (m)')
        # ax2y.set_yticks(np.array([1000,2000,3000,4000,6000,6000,10000]))
        # XXX Not working
        ax2y.yaxis.set_major_formatter(ScalarFormatter())
        ax2y.yaxis.set_minor_formatter(ScalarFormatter())
        #################
        ax2y.set_color('red')
        ax2y.tick_params(colors='red', size=7, width=1,
                         which='both')  # 'both' refers to minor and major axes
        # ax2y.set_yticks([1,2,3,4])
        #ax2.set_xticks([0,5,10,15,20,30,40,50])
        #ax2.set_xticklabels(['0','','10','','20','30','40','50'])
        ax2.set_xticks([0, 4, 8, 12, 16, 20, 24, 32, 40, 48, 56])
        ax2.set_xticklabels(
            ['0', '', '8', '', '16', '', '24', '32', '40', '48', '56'],
            fontsize=11,
            va='center')
        plt.setp(ax2.get_yticklabels(), visible=False)
        # Hodograph
        ax_hod = inset_axes(ax2, '110%', '30%', loc=1)
        ax_hod.set_yticklabels([])
        ax_hod.set_xticklabels([])
        L = 80
        ax_hod.text(0,
                    L - 5,
                    'N',
                    horizontalalignment='center',
                    verticalalignment='center')
        ax_hod.text(L - 5,
                    0,
                    'E',
                    horizontalalignment='center',
                    verticalalignment='center')
        ax_hod.text(-(L - 5),
                    0,
                    'W',
                    horizontalalignment='center',
                    verticalalignment='center')
        ax_hod.text(0,
                    -(L - 5),
                    'S',
                    horizontalalignment='center',
                    verticalalignment='center')
        h = Hodograph(ax_hod, component_range=L)
        h.add_grid(increment=20)
        h.plot_colormapped(
            -u, -v, p, cmap=HEIGHTS
        )  #'viridis_r')  # Plot a line colored by pressure (altitude)
        LG.info('Plotted wind')

        # # print('=-=-=-=-=-=-=')
        # # print(ax2.get_yscale())
        # # print(ax2y.get_yscale())
        # # print('=-=-=-=-=-=-=')
        # # ax2y.yaxis.tick_right()
        # # # ax2y.set_ylim(*reversed(ax.get_ylim()))
        # # ax2y.set_ylim(*ax.get_ylim())
        # # # calc pressure to height
        # # locs = ax2.get_yticks()
        # # labels = [mpcalc.pressure_to_height_std(h*units.hPa) for h in locs]
        # # labels = [round(l.to('m'),1) for l in labels]
        # # for xp,xh in zip(locs,labels):
        # #    print(xp,xh)
        # # ax2y.set_yticks(locs)
        # # ax2y.set_yticklabels([f'{int(l.magnitude)}' for l in labels])
        # Plot only every n windbarb
        n = 4
        inds, = np.where(p > Pmax)
        break_p = 25
        inds_low = inds[:break_p]
        inds_high = inds[break_p:]
        inds = np.append(inds_low[::n], inds_high)
        skew.plot_barbs(
            pressure=p[inds],  #[::n], # * units.hPa,
            u=u[inds],  #[::n],
            v=v[inds],  #[::n],
            xloc=0.985,  # fill_empty=True,
            sizes=dict(emptybarb=0.075, width=0.1, height=0.2))
    # #    # Draw line underneath wind barbs
    # #    line = mlines.Line2D([1.05, 1.05], [0, 1], color='gray', linewidth=0.5,
    # #                         transform=ax.transAxes,
    # #                         dash_joinstyle='round',
    # #                         clip_on=False,
    # #                         zorder=0)
    # #    ax.add_line(line)

    # Add relevant special lines
    # Choose starting temperatures in Kelvin for the dry adiabats
    LG.info('Plot adiabats, and other grid lines')
    skew.ax.text(t0, p[0], f'{t0:.1f}°C', va='top')
    skew.ax.axvline(t0, color=(0.5, 0.5, 0.5), ls='--')
    t0 = units.K * np.arange(243.15, 473.15, 10)
    skew.plot_dry_adiabats(t0=t0,
                           linestyles='solid',
                           colors='gray',
                           linewidth=1)

    # Choose temperatures for moist adiabats
    t0 = units.K * np.arange(281.15, 306.15, 4)
    msa = skew.plot_moist_adiabats(t0=t0,
                                   linestyles='solid',
                                   colors='lime',
                                   linewidths=.75)

    # Choose mixing ratios
    w = np.array([0.001, 0.002, 0.003, 0.005, 0.008, 0.012,
                  0.020]).reshape(-1, 1)

    # Choose the range of pressures that the mixing ratio lines are drawn over
    p_levs = units.hPa * np.linspace(1000, 400, 7)
    skew.plot_mixing_lines(mixing_ratio=w,
                           pressure=p_levs,
                           linestyle='dotted',
                           linewidths=1,
                           colors='lime')

    LG.info('Plotted adiabats, and other grid lines')

    skew.ax.set_ylim(1000, Pmax)
    skew.ax.set_xlim(-20, 43)
    # skew.ax.set_xlim(-30, 40)
    # XXX gvutil not installed
    # gvutil.set_titles_and_labels(ax, maintitle="ATS Rawinsonde: degC + Thin wind")
    # Set axes limits and ticks
    # gvutil.set_axes_limits_and_ticks(ax=ax, xlim=[-30, 50],
    #                 yticks=[1000, 850, 700, 500, 400, 300, 250, 200, 150, 100])

    # Change the style of the gridlines
    ax.grid(True,
            which='major',
            axis='both',
            color='tan',
            linewidth=1.5,
            alpha=0.5)

    ax.set_xlabel("Temperature (C)")
    ax.set_ylabel("P (hPa)")
    if len(title) == 0:
        title = f"{(date).strftime('%d/%m/%Y-%H:%M')} (local time)"
        ax.set_title(title, fontsize=20)
    else:
        ax.set_title(title, fontsize=20)
    if show: plt.show()
    LG.info('saving')
    fig.savefig(fout, bbox_inches='tight', pad_inches=0.1, dpi=150, quality=90)
    LG.info('saved')
    plt.close('all')
예제 #25
0
def plot_soundings(fig,
                   ax,
                   temp,
                   rh,
                   sfc_pressure,
                   centerlat,
                   centerlon,
                   domainsize,
                   model,
                   cape=False,
                   wetbulb=False):
    """
    This function will plot a bunch of little soundings onto a matplotlib fig,ax.

    temp is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change the ylimits for other datasets)

    rh is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change )

    sfc_pressure is an xarray dataarray with surface pressure data (NOT MSLP!)

    centerlat and centerlon are the coordinates around which you want your map
    to be centered. both are floats or integers and are in degrees of latitude
    and degrees of longitude west (i.e. 70W would be input as positive 70 here)

    domainsize is a string either 'local' for ~WFO-size domains or 'regional' for
    NE/SE/Mid-Atlantic-size domains (12 deg lat by 15 deg lon). More will be added soon.

    model is a string that specifies which model is providing data for the plots.
    This determines a few things, most importantly longitude selections. Models
    currently supported are 'GFS','NAM',and 'RAP'

    cape is a boolean to indicate whether you want to overlay parcel paths and
    shade CAPE/CIN on soundings with >100 J/kg of CAPE (this value can be changed)

    wetbulb is a boolean to indicate whether you want to draw wet bulb profiles

    note that this function doesn't "return" anything but if you just call it and
    provide the right arguments, it works.

    for example:
        import soundingmaps as smap
        ...
        smap.plot_soundings(fig,ax1,data['temperature'],data['rh'],30.5,87.5,'local',cape=True)

    """
    r = 5
    if domainsize == "local":
        init_lat_delt = 1.625
        init_lon_delt = 0.45
        lat_delts = [0.2, 0.7, 1.2, 1.75, 2.25, 2.8]
        londelt = 0.76
        startlon = centerlon - 2 + 0.45

    elif domainsize == "regional":
        init_lat_delt = 6
        init_lon_delt = 1.6
        lat_delts = [0.6, 2.5, 4.5, 6.4, 8.4, 10.25]
        londelt = 2.9
        startlon = centerlon - 7.5 + 1.6

    # Lon adjustment for GFS because it's [0,360] not [-180,180]
    if model == 'GFS':
        startlon = 360 - startlon

    # set lat/lon grid from which to pull data to plot soundings
    startlat = centerlat - init_lat_delt

    sound_lats = []
    sound_lons = []
    for i in range(0, 6):
        lats = startlat + lat_delts[i]
        sound_lats.append(lats)

    for i in range(0, r):
        if model == 'GFS':
            lons = startlon - (londelt * i)
        else:
            lons = -startlon - (londelt * i)
        sound_lons.append(lons)

    # this sets how high each row of soundings is on the plot
    plot_elevs = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7]

    # whole bunch of legend stuff
    dashed_red_line = lines.Line2D([], [],
                                   linestyle='solid',
                                   color='r',
                                   label='Temperature')
    dashed_purple_line = lines.Line2D([], [],
                                      linestyle='dashed',
                                      color='purple',
                                      label='0C Isotherm')
    dashed_green_line = lines.Line2D([], [],
                                     linestyle='solid',
                                     color='g',
                                     label='Dew Point')
    grey_line = lines.Line2D([], [], color='darkgray', label='MSLP (hPa)')
    blue_line = lines.Line2D([], [], color='b', label='Wet Bulb')
    pink_line = lines.Line2D([], [],
                             color='fuchsia',
                             label='Surface-Based Parcel Path')
    teal_line = lines.Line2D([], [],
                             linestyle='dashed',
                             color='teal',
                             label='HGZ')
    green_dot = lines.Line2D([], [],
                             marker='o',
                             color='forestgreen',
                             label='LCL')
    black_dot = lines.Line2D([], [],
                             marker='o',
                             color='k',
                             label='Sounding Origin')

    red = mpatches.Patch(color='tab:red', label='CAPE')
    blue = mpatches.Patch(color='tab:blue', label='CIN')

    # do the plotting based on user inputs
    if cape and wetbulb is True:
        print('CAPE + Wetbulb')
        for i, plot_elev in enumerate(plot_elevs):
            soundlat = sound_lats[i]

            if k < 2:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                levs_abv_ground = []
                soundlon = sound_lons[i]
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_pres = temp.lev
                spres = sfc_pressure.interp(lat=soundlat, lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)
                sound_wb = mpcalc.wet_bulb_temperature(
                    sound_pres, sound_temps.data * units.degC, sound_dp)

                #Only want data above the ground
                abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps,
                                                      sound_pres)[0]
                abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp,
                                                      sound_pres)[0]
                abv_sfc_wetb = spt.mask_below_terrain(spres, sound_wb,
                                                      sound_pres)[0]
                pres_abv_ground = spt.mask_below_terrain(
                    spres, sound_temps, sound_pres)[1]

                #sound_wb = sound_wb*units.degC
                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))

                parcel_prof = mpcalc.parcel_profile(
                    pres_abv_ground, abv_sfc_temp[0].data * units.degC,
                    abv_sfc_dewp[0])
                cape = mpcalc.cape_cin(pres_abv_ground,
                                       abv_sfc_temp.data * units.degC,
                                       abv_sfc_dewp, parcel_prof)
                capeout = int(cape[0].m)
                cinout = int(cape[1].m)

                #skew.ax.axvspan(-30, -10, color='cyan', alpha=0.4)

                skew.plot(pres_abv_ground, abv_sfc_wetb, 'b', linewidth=2)
                skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3)
                skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3)

                if capeout > 100:
                    # Shade areas of CAPE and CIN
                    print(pres_abv_ground)
                    print(abv_sfc_temp.data * units.degC)
                    print(parcel_prof)
                    skew.shade_cin(pres_abv_ground,
                                   abv_sfc_temp.data * units.degC, parcel_prof)
                    skew.shade_cape(pres_abv_ground,
                                    abv_sfc_temp.data * units.degC,
                                    parcel_prof)
                    skew.plot(pres_abv_ground,
                              parcel_prof,
                              color='fuchsia',
                              linewidth=1)
                    lcl_pressure, lcl_temperature = mpcalc.lcl(
                        pres_abv_ground[0], abv_sfc_temp.data[0] * units.degC,
                        abv_sfc_dewp[0])
                    skew.plot(lcl_pressure,
                              lcl_temperature,
                              'ko',
                              markerfacecolor='forestgreen')
                    skew.ax.axvline(-30,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)
                    skew.ax.axvline(-10,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)
                skew.plot(975, 0, 'ko', markerfacecolor='k')

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[
            dashed_red_line, dashed_green_line, blue_line, dashed_purple_line,
            teal_line, green_dot, pink_line, red, blue, black_dot
        ],
                        title='Sounding Legend',
                        loc=4,
                        framealpha=1)
    elif cape == True and wetbulb == False:
        print('CAPE no wetbulb')
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k == 0:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                levs_abv_ground = []
                soundlon = sound_lons[i]
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_pres = temp.lev
                spres = sfc_pressure.interp(lat=soundlat, lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)

                abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps,
                                                      sound_pres)[0]
                abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp,
                                                      sound_pres)[0]
                pres_abv_ground = spt.mask_below_terrain(
                    spres, sound_temps, sound_pres)[1]

                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))

                parcel_prof = mpcalc.parcel_profile(
                    pres_abv_ground, abv_sfc_temp[0].data * units.degC,
                    abv_sfc_dewp[0])
                cape = mpcalc.cape_cin(pres_abv_ground,
                                       abv_sfc_temp.data * units.degC,
                                       abv_sfc_dewp, parcel_prof)
                capeout = int(cape[0].m)
                cinout = int(cape[1].m)

                skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3)
                skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3)

                if capeout > 100:
                    # Shade areas of CAPE and CIN
                    skew.shade_cin(pres_abv_ground,
                                   abv_sfc_temp.data * units.degC, parcel_prof)
                    skew.shade_cape(pres_abv_ground,
                                    abv_sfc_temp.data * units.degC,
                                    parcel_prof)
                    skew.plot(pres_abv_ground,
                              parcel_prof,
                              color='fuchsia',
                              linewidth=1)
                    print(abv_sfc_temp)
                    lcl_pressure, lcl_temperature = mpcalc.lcl(
                        pres_abv_ground[0], abv_sfc_temp.data[0] * units.degC,
                        abv_sfc_dewp[0])
                    skew.plot(lcl_pressure,
                              lcl_temperature,
                              'ko',
                              markerfacecolor='forestgreen')
                    skew.ax.axvline(-30,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)
                    skew.ax.axvline(-10,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)

                skew.plot(975, 0, 'ko', markerfacecolor='k')

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[
            dashed_red_line, dashed_green_line, dashed_purple_line, teal_line,
            green_dot, pink_line, red, blue, black_dot
        ],
                        title='Sounding Legend',
                        loc=4,
                        framealpha=1)

    elif wetbulb == True and cape == False:
        print('Wetbulb no CAPE')
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k == 0:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                levs_abv_ground = []
                soundlon = sound_lons[i]
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_pres = temp.lev
                spres = sfc_pressure.interp(lat=soundlat, lon=soundlon)

                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)

                sound_wb = mpcalc.wet_bulb_temperature(
                    sound_pres, sound_temps.data * units.degC, sound_dp)

                abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps,
                                                      sound_pres)[0]
                abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp,
                                                      sound_pres)[0]
                abv_sfc_wetb = spt.mask_below_terrain(spres, sound_wb,
                                                      sound_pres)[0]
                pres_abv_ground = spt.mask_below_terrain(
                    spres, sound_temps, sound_pres)[1]

                #sound_wb = sound_wb*units.degC
                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))

                skew.plot(pres_abv_ground, abv_sfc_wetb, 'b', linewidth=2)
                skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3)
                skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3)

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')
    else:
        print('No Wetbulb or CAPE')
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k == 0:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                sound_pres = temp.lev
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)
                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))
                skew.plot(sound_pres, sound_dp, 'g', linewidth=3)
                skew.plot(sound_pres, sound_temps, 'r', linewidth=3)
                skew.plot(1000, 0, 'ko', markerfacecolor='k')

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[
            dashed_red_line, dashed_green_line, blue_line, dashed_purple_line,
            black_dot
        ],
                        title='Sounding Legend',
                        loc=4,
                        framealpha=1)
예제 #26
0
skew.plot(p, T, 'r')
skew.plot(p, Td, 'g')
skew.plot_barbs(p, u, v)
skew.ax.set_ylim(1000, 100)
skew.ax.set_xlim(-40, 60)
skew.ax.set_xlabel('Temperature [°C]')
skew.ax.set_ylabel('Pressure [hPa]')

# Plot LCL temperature as black dot
skew.plot(lcl_pressure, lcl_temperature, 'ko', markerfacecolor='black')

# Plot the parcel profile as a black line
skew.plot(p, parcel_prof, 'k', linewidth=2)

# Shade areas of CAPE and CIN
skew.shade_cin(p, T, parcel_prof)
skew.shade_cape(p, T, parcel_prof)

# Plot a zero degree isotherm
skew.ax.axvline(0, color='c', linestyle='--', linewidth=2)

# Add the relevant special lines
skew.plot_dry_adiabats()
skew.plot_moist_adiabats()
skew.plot_mixing_lines()

# Add a title
plt.title(str(date) + ' ' + station + ' Punta Arenas')

# Add Legend
plt.legend(['Temperature', 'Dew Point', 'LCL', 'parcel profile'])
예제 #27
0
def main():
    args = get_args()
    setup_logging(args["verbose"])

    # Define input file
    file = args["inputfile"]
    output = args["outputfile"]

    ds = xr.open_dataset(file)

    ds_sel = ds.isel({"sounding": 0})
    ds_sel = ds_sel.sortby(ds_sel.p, ascending=False)
    attrs = ds_sel.attrs
    ds_sel = ds_sel.metpy.quantify()

    p = ds_sel.p
    T = ds_sel.ta
    Td = ds_sel.dp
    wind_speed = ds_sel.wspd
    wind_dir = ds_sel.wdir
    ascend_rate = ds_sel.dz

    launch_time = attrs["time_of_launch_HHmmss"]
    platform = attrs["platform"]
    resolution = attrs["resolution"].replace(" ", "")

    # Filter nans
    idx = np.where(
        (np.isnan(T) + np.isnan(Td) + np.isnan(p) + np.isnan(wind_speed) +
         np.isnan(wind_dir)) is False,
        True,
        False,
    )
    p = p[idx].metpy.convert_units("hPa")
    T = T[idx].metpy.convert_units("degC")
    Td = Td[idx].metpy.convert_units("degC")
    wind_speed = wind_speed[idx].metpy.convert_units("meter / second")
    wind_dir = wind_dir[idx]

    u, v = mpcalc.wind_components(wind_speed, wind_dir)

    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])

    parcel_prof = mpcalc.parcel_profile(p, T[0], Td[0])
    parcel_prof = parcel_prof.metpy.convert_units("degC")

    direction = find_direction_of_sounding(ascend_rate)

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(9, 10))
    skew = SkewT(fig, rotation=30)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.plot(p, T, "r")
    skew.plot(p, Td, "g")
    # Plot only specific barbs to increase visibility
    pressure_levels_barbs = np.logspace(0.1, 1, 50) * 100

    def find_nearest(array, value):
        array = np.asarray(array)
        idx = (np.abs(array - value)).argmin()
        return array[idx]

    # Search for levels by providing pressures
    # (levels is the coordinate not pressure)
    pres_vals = p.isel(level=idx)
    closest_pressure_levels = np.unique(
        [find_nearest(pres_vals, p_) for p_ in pressure_levels_barbs])
    _, closest_pressure_levels_idx, _ = np.intersect1d(pres_vals,
                                                       closest_pressure_levels,
                                                       return_indices=True)

    p_barbs = p.isel({"level": closest_pressure_levels_idx})
    wind_speed_barbs = wind_speed.isel({"level": closest_pressure_levels_idx})
    wind_dir_barbs = wind_dir.isel({"level": closest_pressure_levels_idx})
    u_barbs, v_barbs = mpcalc.wind_components(wind_speed_barbs, wind_dir_barbs)

    # Find nans in pressure
    skew.plot_barbs(p_barbs, u_barbs, v_barbs, xloc=1.06)

    skew.ax.set_ylim(1020, 100)
    skew.ax.set_xlim(-50, 40)

    # Plot LCL as black dot
    skew.plot(lcl_pressure, lcl_temperature, "ko", markerfacecolor="black")

    # Plot the parcel profile as a black line
    skew.plot(pres_vals, parcel_prof, "k", linewidth=1.6)

    # Shade areas of CAPE and CIN
    skew.shade_cin(
        pres_vals.metpy.convert_units("hPa").values,
        T.metpy.convert_units("degC").values,
        parcel_prof.metpy.convert_units("degC").values,
    )
    skew.shade_cape(
        pres_vals.metpy.convert_units("hPa").values,
        T.metpy.convert_units("degC").values,
        parcel_prof.metpy.convert_units("degC").values,
    )

    # Plot a zero degree isotherm
    skew.ax.axvline(0, color="c", linestyle="--", linewidth=2)

    # Add the relevant special lines
    skew.plot_dry_adiabats()
    skew.plot_moist_adiabats()
    skew.plot_mixing_lines()

    # Create a hodograph
    # Create an inset axes object that is 40% width and height of the
    # figure and put it in the upper right hand corner.
    ax_hod = inset_axes(skew.ax, "35%", "35%", loc=1)
    h = Hodograph(ax_hod, component_range=75.0)
    h.add_grid(increment=20)
    h.plot_colormapped(u, v, wind_speed)  # Plot a line colored by wind speed

    # Set title
    sounding_name = ds_sel.sounding.values
    sounding_name_str = str(sounding_name.astype("str"))
    skew.ax.set_title("{sounding}_{direction}".format(
        sounding=sounding_name_str, direction=direction))

    if output is None:
        filename_fmt = "{platform}_SoundingProfile_skew_{launch_time}_{res}.png".format(
            platform=platform, res=resolution, launch_time=launch_time)
        # filename_fmt = launch_time.strftime(filename_fmt)
        output = filename_fmt
    else:
        output = output.format(platform=platform,
                               direction=direction,
                               resolution=resolution)
        # output = launch_time.strftime(output)
    logging.info("Write output to {}".format(output))
    plt.savefig(output)
예제 #28
0
def core_ens(p, T, Td, u, v, p2, T2, Td2, **kwargs):
    #from IPython import embed; embed()
    T = T.to(units.K)
    Td = Td.to(units.K)

    Tmean = T.mean(axis=0)
    Tdmean = Td.mean(axis=0)
    pmean = p.mean(axis=0)
    umean, vmean = u.mean(axis=0), v.mean(axis=0)
    Tstd = np.std(T.data, axis=0) * units.K
    Tdstd = np.std(Td.data, axis=0) * units.K

    # Calculate the parcel profile.
    parcel_prof = mpcalc.parcel_profile(pmean, Tmean[0], Tdmean[0]).to('degC')

    # Create a new figure. The dimensions here give a good aspect ratio
    fig = plt.figure(figsize=(8, 8))
    skew = SkewT(fig, rotation=45)

    # Plot a zero degree isotherm
    skew.ax.axvline(0, color='k', linestyle='--', linewidth=1)

    # Add the relevant special lines
    skew.plot_dry_adiabats(lw=.5)
    skew.plot_moist_adiabats(lw=.5)
    skew.plot_mixing_lines(lw=.5)

    # Plot the data using normal plotting functions, in this case using
    # log scaling in Y, as dictated by the typical meteorological plot
    skew.shade_area(pmean,
                    Tmean - Tstd,
                    Tmean + Tstd,
                    color='r',
                    label='std$_{ens}$ mean$_{dom}$ T$_{fc}$')
    skew.shade_area(pmean,
                    Tdmean - Tdstd,
                    Tdmean + Tdstd,
                    color='g',
                    label='std$_{ens}$ mean$_{dom}$ Td$_{fc}$')
    #skew.plot(p, Tmean+np.std(T), '-', color='grey', lw=1, label='p.999(T)')
    skew.plot(pmean,
              Tmean,
              'r:',
              ms=3,
              lw=1,
              label='mean$_{ens, dom}$ T$_{fc}$')
    skew.plot(pmean,
              Tdmean,
              'g:',
              ms=3,
              lw=1,
              label='mean$_{ens, dom}$ Td$_{fc}$')
    skew.plot_barbs(pmean, umean, vmean)

    # Plot the parcel profile as a black line
    skew.plot(pmean, parcel_prof, 'k', linewidth=.5)

    # Shade areas of CAPE and CIN
    skew.shade_cin(pmean, Tmean, parcel_prof, alpha=0.2)
    skew.shade_cape(pmean, Tmean, parcel_prof, alpha=0.2)

    # nature
    skew.plot(p2,
              T2,
              'r.-',
              ms=5,
              lw=2,
              label='mean$_{ens, dom}$ T$_{nature}$')
    skew.plot(p2,
              Td2,
              'g.-',
              ms=5,
              lw=2,
              label='mean$_{ens, dom}$ Td$_{nature}$')

    skew.ax.set_ylim(1000, 180)
    skew.ax.set_xlim(-20, 40)

    plt.legend(loc='lower left')
    plt.title(kwargs.get('title'))
    fname = kwargs.get('saveto', 'profile.png')
    fig.savefig(fname)
    print(fname, 'saved.')
    plt.close()
예제 #29
0
        parcel_prof = mpcalc.parcel_profile(
            sound_pres, sound_temps[0].data * units.degC, sound_dp[0]
        )
        cape = mpcalc.cape_cin(
            sound_pres, sound_temps.data * units.degC, sound_dp, parcel_prof
        )
        capeout = int(cape[0].m)
        cinout = int(cape[1].m)

        skew.plot(sound_pres, sound_dp, "g", linewidth=3)
        skew.plot(sound_pres, sound_temps, "r", linewidth=3)

        if capeout > capemin:
            # Shade areas of CAPE and CIN
            skew.shade_cin(sound_pres, sound_temps.data * units.degC, parcel_prof)
            skew.shade_cape(sound_pres, sound_temps.data * units.degC, parcel_prof)
            skew.plot(sound_pres, parcel_prof, color="fuchsia", linewidth=1)

        skew.ax.axvline(0, color="purple", linestyle="--", linewidth=3)
        skew.ax.set_ylim((1000, ptop))
        skew.ax.axis("off")
        # skew.ax.text(0.1,0.1,str(soundlat)+'  '+str(soundlon))

    for i in range(0, 5):
        soundlat = 31
        soundlon = 360 - (startlat + (londelt * i))
        sound_temps = data["temperature"].interp(lat=soundlat, lon=soundlon) - 273.15
        sound_rh = data["rh"].interp(lat=soundlat, lon=soundlon)
        sound_dp = mpcalc.dewpoint_from_relative_humidity(
            sound_temps.data * units.degC, sound_rh.data * units.percent