Esempio n. 1
0
def virt_temp(t, q):
    """
    Compute virtual temperature in [K] from temperature and
    specific humidity.

    Arguments:
    t -- temperature in [K]
    q -- specific humidity in [kg/kg]

    t and q can be scalars of NumPy arrays. They just have to either all
    scalars, or all arrays.

    Returns: Virtual temperature in [K]. Same dimension as input fields.
    """
    t = units.Quantity(t, "K")
    mix_rat = mpcalc.mixing_ratio_from_specific_humidity(q)
    v_temp = mpcalc.virtual_temperature(t, mix_rat)
    return v_temp
Esempio n. 2
0
def test_virtual_temperature():
    """Test virtual temperature calculation."""
    t = 288. * units.kelvin
    qv = .0016  # kg/kg
    tv = virtual_temperature(t, qv)
    assert_almost_equal(tv, 288.2796 * units.kelvin, 3)
                    df_selected_time['mixing_ratio'] = mpcalc.mixing_ratio(
                        VP, p)
                    SMR = df_selected_time[
                        'saturation_mixing_ratio'].values * units('g/kg')
                    MR = df_selected_time['mixing_ratio'].values * units(
                        'g/kg')

                    # Calculate relative humidity
                    df_selected_time['relative_humidity_from_dewpoint'] \
                        = mpcalc.relative_humidity_from_dewpoint(T, Td)
                    df_selected_time['relative_humidity_from_mixing_ratio'] \
                        = mpcalc.relative_humidity_from_mixing_ratio(MR, T, p)

                    # Calculate virtual temperature
                    df_selected_time['virtual_temperature'] \
                        = mpcalc.virtual_temperature(T, MR)

                    # Calculate virtual potential temperature
                    df_selected_time['virtual_potential_temperature'] \
                        = mpcalc.virtual_potential_temperature(p, T, MR)

                    print('df_selected_time after drop nan.\n{0}'.format(
                        df_selected_time))

                    df_selected_time.to_csv(r'{0}{1}{2}_{3}_solution.csv'\
                            .format(dir_name, save_dir_name, filename_el[-5], selected_time[:13]))

                    p = df_selected_time['pressure'].values * units.hPa
                    T = df_selected_time['temperature'].values * units.degC
                    Td = df_selected_time['dewpoint'].values * units.degC
                    wind_speed = df_selected_time['speed'].values * units.knots
Esempio n. 4
0
def EnergyMassPlot(pressure, temperature, dewpoint,
                  height, uwind, vwind, sphum=None, rh=None,
                  label='', size=(12,10), return_fig=False): 
    p=pressure
    Z=height
    T=temperature
    Td=dewpoint
    if isinstance(sphum,np.ndarray) and isinstance(rh,np.ndarray):
        q=sphum
        qs=q/rh
    else:
        q = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(Td),p)
        qs= mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T),p)
    
    s = g*Z + Cp_d*T 
    sv= g*Z + Cp_d*mpcalc.virtual_temperature(T,q)
    h = s            + Lv*q
    hs= s            + Lv*qs
    
    parcel_Tprofile = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')
    CAPE,CIN = mpcalc.cape_cin(p,T,Td,parcel_Tprofile)
    ELp,ELT = mpcalc.el(p,T,Td)
    ELindex = np.argmin(np.abs(p - ELp))
    lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
    
    p_PWtop = max(200*units.mbar, min(p) +1*units.mbar)
    PW = mpcalc.precipitable_water(Td,p, top=p_PWtop)
    PWs = mpcalc.precipitable_water(T,p, top=p_PWtop)
    CRH = (PW/PWs).magnitude *100. 
    
    fig,ax=setup_fig(size=size,label=label)
    
    ax.plot(s  /1000, p, color='r', linewidth=1.5)  ### /1000 for kJ/kg
    ax.plot(sv /1000, p, color='r', linestyle='-.') 
    ax.plot(h  /1000, p, color='b', linewidth=1.5) 
    ax.plot(hs /1000, p, color='r', linewidth=1.5) 
    ### RH rulings between s and h lines: annotate near 800 hPa level
    annot_level = 800 #hPa
    idx = np.argmin(np.abs(p - annot_level *units.hPa))
    right_annot_loc = 380
    for iRH in np.arange(10,100,10):
        ax.plot( (s+ Lv*qs*iRH/100.)/1000, p, linewidth=0.5, linestyle=':', color='k')
        ax.annotate(str(iRH), xy=( (s[idx]+Lv*qs[idx]*iRH/100.)/1000, annot_level),                    
                    horizontalalignment='center',fontsize=6)
    ax.annotate('RH (%)', xy=(right_annot_loc, annot_level), fontsize=10)
    
    if  not np.isnan(CAPE.magnitude) and CAPE.magnitude >10:  
        parcelh  = h [0]        # for a layer mean: np.mean(h[idx1:idx2])
        parcelsv = sv[0]
        parcelp0 = p[0]

        # Undilute parcel
        ax.plot( (1,1)*parcelh/1000., (1,0)*parcelp0, linewidth=0.5, color='g')
        maxbindex = np.argmax(parcel_Tprofile - T)
        ax.annotate('CAPE='+str(int(CAPE.magnitude)), 
                    xy=(parcelh/1000., p[maxbindex]), color='g')

        # Plot LCL at saturation point, above the lifted sv of the surface parcel 
        lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0])
        ax.annotate('LCL', xy=(sv[0]/1000., lcl_pressure), fontsize=10, color='g', horizontalalignment='right')
        # Purple fill for negative buoyancy below LCL:
        ax.fill_betweenx(p, sv/1000., parcelsv/1000., where=p>lcl_pressure, facecolor='purple', alpha=0.4)

        # Positive moist convective buoyancy in green 
        # Above LCL:
        ax.fill_betweenx(p, hs/1000., parcelh/1000., where= parcelh>hs, facecolor='g', alpha=0.4)


        # Depict Entraining parcels
        # Parcel mass solves dM/dz = eps*M, solution is M = exp(eps*Z)
        # M=1 at ground without loss of generality
        entrainment_distance = 10000., 5000., 2000. 
        ax.annotate('entrain: 10,5,2 km',  xy=(parcelh/1000, 140), color='g', 
                    fontsize=8, horizontalalignment='right')
        ax.annotate('parcel h',            xy=(parcelh/1000, 120), color='g', 
                    fontsize=10, horizontalalignment='right')

        for ED in entrainment_distance: 
            eps = 1.0 / (ED*units.meter)
            M = np.exp(eps * (Z-Z[0]).to('m')).to('dimensionless')

            # dM is the mass contribution at each level, with 1 at the origin level. 
            M[0] = 0
            dM = np.gradient(M)

            # parcel mass is a  sum of all the dM's at each level
            # conserved linearly-mixed variables like h are weighted averages 
            hent = np.cumsum(dM*h) / np.cumsum(dM)

            ax.plot( hent[0:ELindex+3]/1000., p[0:ELindex+3], linewidth=0.5, color='g')
        ### Internal waves (100m adiabatic displacements, assumed adiabatic: conserves s, sv, h). 
    dZ = 100 *units.meter

    # depict displacements at sounding levels nearest these target levels
    targetlevels = [900,800,700,600,500,400,300,200]*units.hPa
    for ilev in targetlevels:
        idx = np.argmin(np.abs(p - ilev))

        # dT: Dry lapse rate dT/dz_dry is -g/Cp
        dT = (-g/Cp_d *dZ).to('kelvin')    
        Tdisp = T[idx].to('kelvin') + dT

        # dp: hydrostatic
        rho = (p[idx]/Rd/T[idx])
        dp = -rho*g*dZ

        # dhsat
        #qs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T)     ,p)
        dqs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(Tdisp) ,p[idx]+dp) -qs[idx]
        dhs = g*dZ + Cp_d*dT + Lv*dqs

        # Whiskers on the data plots
        ax.plot( (hs[idx]+dhs*(-1,1))/1000, p[idx]+dp*(-1,1), linewidth=3, color='r')  
        ax.plot( (s [idx]    *( 1,1))/1000, p[idx]+dp*(-1,1), linewidth=3, color='r')  
        ax.plot( (h [idx]    *( 1,1))/1000, p[idx]+dp*(-1,1), linewidth=3, color='b')  

        # annotation to explain it 
        if ilev == 600*ilev.units:
            ax.plot(right_annot_loc*hs.units +dhs*(-1,1)/1000, p[idx]+dp*(-1,1), linewidth=3, color='r')  
            ax.annotate('+/- 100m', xy=(right_annot_loc,600), fontsize=8)
            ax.annotate('  internal', xy=(right_annot_loc,630), fontsize=8)
            ax.annotate('  waves', xy=(right_annot_loc,660), fontsize=8)


    ### Blue fill proportional to precipitable water, and blue annotation
    ax.fill_betweenx(p, s/1000., h/1000., where=h > s, facecolor='b', alpha=0.4)

    # Have to specify the top of the PW integral. 
    # I want whole atmosphere of course, but 200 hPa captures it all really. 
    #import metpy.calc as mpcalc
    p_PWtop = max(200*units.mbar, min(p) +1*units.mbar)
    PW = mpcalc.precipitable_water(Td,p, top=p_PWtop)
    PWs = mpcalc.precipitable_water(T,p, top=p_PWtop)
    CRH = (PW/PWs).magnitude *100. 

    # PW annotation arrow tip at 700 mb
    idx = np.argmin(np.abs(p - 700*p.units))
    centerblue = (s[idx]+h[idx])/2.0 /1000.

    ax.annotate('CWV='+str(round(PW.to('mm').magnitude, 1))+'mm',
                xy=(centerblue, 700), xytext=(285, 200), 
                color='blue', fontsize=15,
                arrowprops=dict(width = 1, edgecolor='blue', shrink=0.02),
                )
    ax.annotate('(' + str(round(CRH,1)) +'% of sat)',
                xy=(285, 230), color='blue', fontsize=12)



    ### Surface water values at 1C intervals, for eyeballing surface fluxes
    sT = np.trunc(T[0].to('degC'))
    sTint = int(sT.magnitude)

    for idT in [-2,0,2,4]:
        ssTint = sTint + idT # UNITLESS degC integers, for labels

        # Kelvin values for computations
        ssTC = ssTint * units.degC
        ssTK = ssTC.to('kelvin')
        ss = g*Z[0] + Cp_d*ssTK 
        hs = ss     + Lv*mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(ssTK) ,p[0])

        ax.annotate(str(ssTint), xy=(ss/1000., p[0]+0*p.units), 
                    verticalalignment='top', horizontalalignment='center',
                    color='red', fontsize=7)
        ax.annotate(str(ssTint), xy=(hs/1000., p[0]+0*p.units), 
                    verticalalignment='top', horizontalalignment='center',
                    color='red', fontsize=9)
        ax.annotate('\u00b0C water', xy=(right_annot_loc, p[0]), verticalalignment='top', 
                    fontsize=10, color='r')
    if return_fig:
        return ax,fig
Esempio n. 5
0
def calculate_stability_indicies(
    ds,
    temp_name='temperature',
    td_name='dewpoint_temperature',
    p_name='pressure',
    rh_name='relative_humidity',
    moving_ave_window=0,
):
    """
    Function for calculating stability indices from sounding data.

    Parameters
    ----------
    ds : ACT dataset
        The dataset to compute the stability indicies of. Must have
        temperature, dewpoint, and pressure in vertical coordinates.
    temp_name : str
        The name of the temperature field.
    td_name : str
        The name of the dewpoint field.
    p_name : str
        The name of the pressure field.
    rh_name : str
        The name of the relative humidity field.
    moving_ave_window : int
        Number of points to do a moving average on sounding data to reduce
        noise. This is useful if noise in the sounding is preventing parcel
        ascent.

    Returns
    -------
    ds : ACT dataset
        An ACT dataset with additional stability indicies added.

    """
    if not METPY_AVAILABLE:
        raise ImportError(
            'MetPy need to be installed on your system to ' + 'calculate stability indices'
        )

    t = ds[temp_name]
    td = ds[td_name]
    p = ds[p_name]
    rh = ds[rh_name]

    if not hasattr(t, 'units'):
        raise AttributeError('Temperature field must have units' + ' for ACT to discern!')

    if not hasattr(td, 'units'):
        raise AttributeError('Dewpoint field must have units' + ' for ACT to discern!')

    if not hasattr(p, 'units'):
        raise AttributeError('Pressure field must have units' + ' for ACT to discern!')
    if t.units == 'C':
        t_units = units.degC
    else:
        t_units = getattr(units, t.units)

    if td.units == 'C':
        td_units = units.degC
    else:
        td_units = getattr(units, td.units)

    p_units = getattr(units, p.units)
    rh_units = getattr(units, rh.units)

    # Sort all values by decreasing pressure
    t_sorted = np.array(t.values)
    td_sorted = np.array(td.values)
    p_sorted = np.array(p.values)
    rh_sorted = np.array(rh.values)
    ind_sort = np.argsort(p_sorted)
    t_sorted = t_sorted[ind_sort[-1:0:-1]]
    td_sorted = td_sorted[ind_sort[-1:0:-1]]
    p_sorted = p_sorted[ind_sort[-1:0:-1]]
    rh_sorted = rh_sorted[ind_sort[-1:0:-1]]

    if moving_ave_window > 0:
        t_sorted = np.convolve(t_sorted, np.ones((moving_ave_window,)) / moving_ave_window)
        td_sorted = np.convolve(td_sorted, np.ones((moving_ave_window,)) / moving_ave_window)
        p_sorted = np.convolve(p_sorted, np.ones((moving_ave_window,)) / moving_ave_window)
        rh_sorted = np.convolve(rh_sorted, np.ones((moving_ave_window,)) / moving_ave_window)

    t_sorted = t_sorted * t_units
    td_sorted = td_sorted * td_units
    p_sorted = p_sorted * p_units
    rh_sorted = rh_sorted * rh_units

    # Calculate mixing ratio
    mr = mpcalc.mixing_ratio_from_relative_humidity(p_sorted, t_sorted, rh_sorted)

    # Discussion of issue #361 use virtual temperature.
    vt = mpcalc.virtual_temperature(t_sorted, mr)

    t_profile = mpcalc.parcel_profile(p_sorted, t_sorted[0], td_sorted[0])

    # Calculate parcel trajectory
    ds['parcel_temperature'] = t_profile.magnitude
    ds['parcel_temperature'].attrs['units'] = t_profile.units

    # Calculate CAPE, CIN, LCL
    sbcape, sbcin = mpcalc.surface_based_cape_cin(p_sorted, vt, td_sorted)

    lcl = mpcalc.lcl(p_sorted[0], t_sorted[0], td_sorted[0])
    try:
        lfc = mpcalc.lfc(p_sorted[0], t_sorted[0], td_sorted[0])
    except IndexError:
        lfc = np.nan * p_sorted.units

    mucape, mucin = mpcalc.most_unstable_cape_cin(p_sorted, vt, td_sorted)

    where_500 = np.argmin(np.abs(p_sorted - 500 * units.hPa))
    li = t_sorted[where_500] - t_profile[where_500]

    ds['surface_based_cape'] = sbcape.magnitude
    ds['surface_based_cape'].attrs['units'] = 'J/kg'
    ds['surface_based_cape'].attrs['long_name'] = 'Surface-based CAPE'
    ds['surface_based_cin'] = sbcin.magnitude
    ds['surface_based_cin'].attrs['units'] = 'J/kg'
    ds['surface_based_cin'].attrs['long_name'] = 'Surface-based CIN'
    ds['most_unstable_cape'] = mucape.magnitude
    ds['most_unstable_cape'].attrs['units'] = 'J/kg'
    ds['most_unstable_cape'].attrs['long_name'] = 'Most unstable CAPE'
    ds['most_unstable_cin'] = mucin.magnitude
    ds['most_unstable_cin'].attrs['units'] = 'J/kg'
    ds['most_unstable_cin'].attrs['long_name'] = 'Most unstable CIN'
    ds['lifted_index'] = li.magnitude
    ds['lifted_index'].attrs['units'] = t_profile.units
    ds['lifted_index'].attrs['long_name'] = 'Lifted index'
    ds['level_of_free_convection'] = lfc.magnitude
    ds['level_of_free_convection'].attrs['units'] = lfc.units
    ds['level_of_free_convection'].attrs['long_name'] = 'Level of free convection'
    ds['lifted_condensation_level_temperature'] = lcl[1].magnitude
    ds['lifted_condensation_level_temperature'].attrs['units'] = lcl[1].units
    ds['lifted_condensation_level_temperature'].attrs[
        'long_name'
    ] = 'Lifted condensation level temperature'
    ds['lifted_condensation_level_pressure'] = lcl[0].magnitude
    ds['lifted_condensation_level_pressure'].attrs['units'] = lcl[0].units
    ds['lifted_condensation_level_pressure'].attrs[
        'long_name'
    ] = 'Lifted condensation level pressure'
    return ds
def f(fullname, selected_time):
    fullname_el = fullname.split('/')
    #fullname_el = fullname.split('\\')
    filename = fullname_el[-1]
    filename_el = filename.split('_')
    save_base_dir_name = '../1data/'
    save_dir_name = '{0}{1}/'.format(save_base_dir_name + dir_name, obs_year)
    print('site : {0}'.format(dir_name))

    if os.path.isfile('{0}{1}_{2}_student.csv'\
                      .format(save_dir_name, filename_el[-5], selected_time[:13]))\
        and os.path.isfile('{0}{1}_{2}_solution.csv'\
                      .format(save_dir_name, filename_el[-5], selected_time[:13])):
        write_log(log_file, '{3} ::: {0}{1}_{2} files are already exist'\
                  .format(save_dir_name, filename_el[-5], selected_time[:13], datetime.now()))
    else:
        try:
            f = lambda s: selected_time in s
            ids = df['time'].apply(f)
            df_selected_time = df[ids]
            df_selected_time = df_selected_time.sort_values('pressure',
                                                            ascending=False)

            print('filename : {0}'.format(fullname))
            print('df_selected_time.\n{0}'.format(df_selected_time))

            df_selected_time.to_csv(r'{0}{1}_{2}_student.csv'\
                      .format(save_dir_name, filename_el[-5], selected_time[:13]))

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

            p = df_selected_time['pressure'].values * units.hPa
            T = df_selected_time['temperature'].values * units.degC
            Td = df_selected_time['dewpoint'].values * units.degC
            wind_speed = df_selected_time['speed'].values * units.knots
            wind_dir = df_selected_time['direction'].values * units.degrees
            u, v = mpcalc.wind_components(wind_speed, wind_dir)

            # Calculate web bulb temperature
            df_selected_time['wet_bulb_T'] = mpcalc.wet_bulb_temperature(
                p, T, Td)

            # Calculate potential temperature
            df_selected_time['potential_T'] = mpcalc.potential_temperature(
                p, T)
            df_selected_time['potential_T_C'] = df_selected_time[
                'potential_T'].values - 273.15

            # Calculate saturation vaper pressure
            df_selected_time[
                'saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure(
                    T)
            df_selected_time[
                'vaper_pressure'] = mpcalc.saturation_vapor_pressure(Td)
            SVP = df_selected_time[
                'saturation_vaper_pressure'].values * units.hPa
            VP = df_selected_time['vaper_pressure'].values * units.hPa

            # Calculate mixing ratio
            df_selected_time['saturation_mixing_ratio'] = mpcalc.mixing_ratio(
                SVP, p)
            df_selected_time['mixing_ratio'] = mpcalc.mixing_ratio(VP, p)
            SMR = df_selected_time['saturation_mixing_ratio'].values * units(
                'g/kg')
            MR = df_selected_time['mixing_ratio'].values * units('g/kg')

            # Calculate relative humidity
            df_selected_time['relative_humidity_from_dewpoint'] \
                = mpcalc.relative_humidity_from_dewpoint(T, Td)
            df_selected_time['relative_humidity_from_mixing_ratio'] \
                = mpcalc.relative_humidity_from_mixing_ratio(MR, T, p)

            # Calculate virtual temperature
            df_selected_time['virtual_temperature'] \
                = mpcalc.virtual_temperature(T, MR)

            # Calculate virtual potential temperature
            df_selected_time['virtual_potential_temperature'] \
                = mpcalc.virtual_potential_temperature(p, T, MR)

            print('df_selected_time after drop nan.\n{0}'.format(
                df_selected_time))

            df_selected_time.to_csv(r'{0}{1}_{2}_solution.csv'\
                      .format(save_dir_name, filename_el[-5], selected_time[:13]))

        except Exception as err:
            write_log(err_log_file, '{4} ::: {0} with {1}{2} on {3}'\
                      .format(err, dir_name, filename, selected_time[:13], datetime.now()))
    print('Thread {0} is finished'.format(selected_time))
    return 0  # Return a dummy value
Esempio n. 7
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()
ds = ds.sel(time=dt.strftime('%Y-%m-%dT%H:%M:%S'))  # reduce the dataset to the RAP analysis (starting) time from 'dt'

#### Want to list the field names + some info from this xarray Dataset? Uncomment the below 6 lines!
#fieldNames = list(ds.variables.keys())
#for fieldName in fieldNames:
#    try:
#        print('%s -- "%s" [%s]' % (fieldName, ds[fieldName].long_name, ds[fieldName].units))
#    except AttributeError:
#        print(fieldName)

#### Compute 1000-500-hPa geopotential thickness (pressure coordinates are in units of Pa)
thick = ds.Geopotential_height_isobaric.sel(isobaric=50000) - ds.Geopotential_height_isobaric.sel(isobaric=100000)

#### Compute 1000-500-hPa pressure-weighted mean virtual temperature
MR = mpcalc.mixing_ratio_from_relative_humidity(ds.isobaric, ds.Temperature_isobaric, ds.Relative_humidity_isobaric)
Tvirt = mpcalc.virtual_temperature(ds.Temperature_isobaric, MR, molecular_weight_ratio=0.6219569100577033)
layer = slice(50000,100000)  # 1000-500-hPa layer
dp = np.zeros(ds.isobaric.sel(isobaric=layer).size, dtype=float)  # NumPy array to store dp, the depth in Pa of each layer
dp[:-1] = np.abs(np.ediff1d(ds.isobaric.sel(isobaric=layer).values))
dp[-1] = dp[-2]  # np.ediff1d produces an array 1 smaller than the input, so make an assumption here for final value
dp = xr.DataArray(data=dp.copy(), dims=['isobaric'], coords={'isobaric':ds.isobaric.sel(isobaric=layer)},
                  attrs={'units': ds.isobaric.units})
TvirtLayer = np.sum(Tvirt.sel(isobaric=layer)*ds.isobaric.sel(isobaric=layer)*dp, axis=0) / \
             np.sum(ds.isobaric.sel(isobaric=layer)*dp, axis=0)

#### Convert x/y coordinates to latitude & longitude (note: steps are NOT via xarray as I'm debugging that approach)
dsProjDict = ds.LambertConformal_Projection.attrs  # obtain the source data map projection
R = dsProjDict['earth_radius']
dsProj = ccrs.LambertConformal(central_longitude=dsProjDict['longitude_of_central_meridian']-360.,
                               central_latitude=dsProjDict['latitude_of_projection_origin'],
                               standard_parallels=[dsProjDict['standard_parallel']],
Esempio n. 9
0
def test_virtual_temperature():
    """Test virtual temperature calculation."""
    t = 288. * units.kelvin
    qv = .0016 * units.dimensionless  # kg/kg
    tv = virtual_temperature(t, qv)
    assert_almost_equal(tv, 288.2796 * units.kelvin, 3)