Beispiel #1
0
def theta_plots(pressure, temperature, mixing_ratio):
    """
    plots for vertical profiles of potential temperature, equivalent potential temperature, 
    and saturated equivalent potential temperature
    """
    p = pressure * units('mbar')
    T = temperature * units('degC')
    q = mixing_ratio * units('kilogram/kilogram')

    lev = find_nearest(p.magnitude, 100)
    Td = mpcalc.dewpoint(mpcalc.vapor_pressure(p, q))  # dewpoint
    theta = mpcalc.potential_temperature(p, T)
    theta_e = mpcalc.equivalent_potential_temperature(p, T, Td)
    theta_es = mpcalc.equivalent_potential_temperature(p, T, T)

    plt.figure(figsize=(7, 7))
    plt.plot(theta[:lev], p[:lev], '-ok')
    plt.plot(theta_e[:lev], p[:lev], '-ob')
    plt.plot(theta_es[:lev], p[:lev], '-or')
    plt.xlabel('Temperature [K]', fontsize=12)
    plt.ylabel('Pressure [hpa]', fontsize=12)
    plt.gca().invert_yaxis()
    plt.legend(['$\\theta$', '$\\theta_e$', '$\\theta_{es}$'], loc=1)
    plt.grid()
    return (plt)
Beispiel #2
0
def test_equivalent_potential_temperature():
    """Test equivalent potential temperature calculation."""
    p = 1000 * units.mbar
    t = 293. * units.kelvin
    td = 280. * units.kelvin
    ept = equivalent_potential_temperature(p, t, td)
    assert_almost_equal(ept, 311.18586467284007 * units.kelvin, 3)
Beispiel #3
0
def test_equivalent_potential_temperature():
    """Test equivalent potential temperature calculation."""
    p = 1000 * units.mbar
    t = 293. * units.kelvin
    td = 280. * units.kelvin
    ept = equivalent_potential_temperature(p, t, td)
    assert_almost_equal(ept, 311.18586467284007 * units.kelvin, 3)
Beispiel #4
0
def getDataFrame_UpperAir(model, station, init, hour):
    bufrData = BUFKIT.getBufkitData(model, station, init)

    if bufrData != False:  # Verify data found
        modelSoundings = bufrData.SoundingParameters
        surfaceData = bufrData.SurfaceParameters[hour]
        soundingData = modelSoundings[hour + 1]

        z = [0 * units.meters]
        p = [surfaceData.pres]
        T = [surfaceData.t2ms]
        Td = [surfaceData.td2m]
        #Tw = [mpcalc.wet_bulb_temperature(surfaceData.pres, surfaceData.t2ms, surfaceData.td2m)]
        theta = [
            mpcalc.potential_temperature(surfaceData.pres, surfaceData.t2ms)
        ]
        theta_e = [
            mpcalc.equivalent_potential_temperature(surfaceData.pres,
                                                    surfaceData.t2ms,
                                                    surfaceData.td2m)
        ]
        u = [surfaceData.uwnd]
        v = [surfaceData.vwnd]

        for level in soundingData:
            z.append(level.hght)
            p.append(level.pres)
            T.append(level.tmpc)
            Td.append(level.dwpc)
            #Tw.append(mpcalc.wet_bulb_temperature(level.pres, level.tmpc, level.dwpc))
            theta.append(mpcalc.potential_temperature(level.pres, level.tmpc))
            theta_e.append(
                mpcalc.equivalent_potential_temperature(
                    level.pres, level.tmpc, level.dwpc))
            uv = mpcalc.wind_components(level.sknt, level.drct)
            u.append(uv[0])
            v.append(uv[1])

        return pd.DataFrame(list(zip(z, p, T, Td, theta, theta_e, u, v)),
                            columns=[
                                'height', 'pressure', 'temperature',
                                'dewpoint', 'theta', 'theta_e', 'u_wind',
                                'v_wind'
                            ])
    else:
        return False
Beispiel #5
0
def add_eqiv_potential_temp(tbs):
    temp = tbs['temp'].values * units.celsius
    rh = tbs['rh'].values * units.percent
    press = tbs['atm_pressure'].values * units.millibar

#     dewpt_pint = calc.dewpoint_rh(temp, rh)
    dewpt_pint = calc.dewpoint_from_relative_humidity(temp, rh)
    dewpt = np.array(dewpt_pint)

    tbs['dew_point'] = dewpt
    tbs['equiv_potential_temperature'] = np.array(calc.equivalent_potential_temperature(press, temp, dewpt_pint))
    return
Beispiel #6
0
def equivalent_potential_temperature(pressure, temperature, dewpoint):
    r"""This method calls the metpy.calc function equivalent_potential_temperature
        which takes the pint.Quantity objects containing the isobaric level value
        and the temperature at that level and, assuming saturated water vapor,
        produces the corresponding equivalent potential temperature with the reference
        pressure being 1000 millibars.

    """

    #eqpotemp = calc.equivalent_potential_temperature(pressure, temperature, dewpoint)

    return calc.equivalent_potential_temperature(pressure, temperature,
                                                 dewpoint)
Beispiel #7
0
def calc_fronts(u, v, q, t, lon, lat, date_list):
    '''
    Parse era5 variables to kinematics(), to calculate various thermal and kinematic front parameters. 
    12 are computed, but for brevity, only four are returned for now.
    '''

    #Using MetPy, derive equivalent potential temperature
    ta_unit = units.units.K * t
    dp_unit = mpcalc.dewpoint_from_specific_humidity(
        q * units.units.dimensionless, ta_unit, 850 * units.units.hectopascals)
    thetae = np.array(
        mpcalc.equivalent_potential_temperature(850 * units.units.hectopascals,
                                                ta_unit, dp_unit))

    #From the lat-lon information accompanying the ERA5 data, resconstruct 2d coordinates and grid spacing (dx, dy)
    x, y = np.meshgrid(lon, lat)
    dx, dy = mpcalc.lat_lon_grid_deltas(x, y)

    #Derive various kinematic/thermal diagnostics for each time step
    kinemats = [
        kinematics(u[i], v[i], thetae[i], dx, dy, y, smooth=True, sigma=2)
        for i in np.arange(len(date_list))
    ]
    F = [kinemats[i][0] for i in np.arange(len(date_list))
         ]  #Frontogenesis function (degC / 100 km / 3 hr)
    Fn = [kinemats[i][1] for i in np.arange(len(date_list))
          ]  #Frontogenetical function (deg C / 100 km / 3 hr)
    Fs = [kinemats[i][2] for i in np.arange(len(date_list))
          ]  #Rotational component of frontogensis (deg C/ 100 km / 3 hr)
    icon = [kinemats[i][3] for i in np.arange(len(date_list))
            ]  #Instantaneous contraction rate (s^-1 * 1e5)
    vgt = [kinemats[i][4] for i in np.arange(len(date_list))
           ]  #Horizontal velovity gradient tensor magnitude (s^-1 * 1e5)
    conv = [kinemats[i][5]
            for i in np.arange(len(date_list))]  #Convergence (s^-1 * 1e5)
    vo = [kinemats[i][6]
          for i in np.arange(len(date_list))]  #Relative vorticity (s^-1 * 1e5)
    tfp = [kinemats[i][7] for i in np.arange(len(date_list))
           ]  #Thermal front parameter (km^-2)
    mag_te = [kinemats[i][8] for i in np.arange(len(date_list))
              ]  #Magnitude of theta-e gradient (100 km ^-1)
    v_f = [kinemats[i][9]
           for i in np.arange(len(date_list))]  #Advection of TFP (m/s)
    thetae = [kinemats[i][10] for i in np.arange(len(date_list))
              ]  #Theta-e (K), may be smoothed depending on arguments
    cond = [kinemats[i][11]
            for i in np.arange(len(date_list))]  #Extra condition

    return [thetae, mag_te, tfp, v_f]
Beispiel #8
0
def compute_thetae(dset, tvar='t', rvar='r'):
    rh = mpcalc.dewpoint_from_relative_humidity(dset['t'], dset['r'] / 100.)
    theta_e = mpcalc.equivalent_potential_temperature(850 * units.hPa,
                                                      dset['t'], rh).to('degC')

    theta_e = xr.DataArray(theta_e.magnitude,
                           coords=dset['t'].coords,
                           attrs={
                               'standard_name':
                               'Equivalent potential temperature',
                               'units': theta_e.units
                           },
                           name='theta_e')

    return xr.merge([dset, theta_e])
Beispiel #9
0
def calc_thta_vir(united_data):
    """
    returns virtual potential temperature (K)
    and equvalent potential temperaure (K)
    """

    pres = united_data['PRES']
    temp = united_data['TEMP']
    rh = united_data['HUM']
    mixing = mpcalc.mixing_ratio_from_relative_humidity(rh, temp, pres)
    theta_vir = mpcalc.virtual_potential_temperature(pres, temp, mixing)

    td = mpcalc.dewpoint_rh(temp, rh)
    theta_e = mpcalc.equivalent_potential_temperature(pres, temp, td)

    return theta_vir, theta_e
Beispiel #10
0
def main():
    """In the main function we basically read the files and prepare the variables to be plotted.
    This is not included in utils.py as it can change from case to case."""
    file = glob(input_file)
    print_message('Using file '+file[0])
    dset = xr.open_dataset(file[0])
    dset = dset.metpy.parse_cf()

    # Select 850 hPa level using metpy
    dset_850hpa = dset
    theta_e = mpcalc.equivalent_potential_temperature(850 * units.hPa, dset['t'].metpy.sel(vertical=850 * units.hPa),
                     mpcalc.dewpoint_rh(dset['t'].metpy.sel(vertical=850 * units.hPa), dset['r'].metpy.sel(vertical=850 * units.hPa)/100.)).to(units.degC)

    mslp = dset['prmsl'].metpy.unit_array.to('hPa')
    lon, lat = get_coordinates(dset)

    time = pd.to_datetime(dset.time.values)
    cum_hour=np.array((time-time[0]) / pd.Timedelta('1 hour')).astype("int")

    levels_thetae = np.arange(-25., 75., 1.)
    levels_mslp = np.arange(mslp.min().astype("int"), mslp.max().astype("int"), 7.)

    for projection in projections:# This works regardless if projections is either single value or array
        fig = plt.figure(figsize=(figsize_x, figsize_y))
        ax  = plt.gca()        
        m, x, y =get_projection(lon, lat, projection)
        # Create a mask to retain only the points inside the globe
        # to avoid a bug in basemap and a problem in matplotlib
        mask = np.logical_or(x<1.e20, y<1.e20)
        x = np.compress(mask,x)
        y = np.compress(mask,y)
        # Parallelize the plotting by dividing into chunks and processes 
        # All the arguments that need to be passed to the plotting function
        args=dict(m=m, x=x, y=y, ax=ax,
                 theta_e=np.compress(mask, theta_e, axis=1), mslp=np.compress(mask, mslp, axis=1),
                 levels_thetae=levels_thetae,levels_mslp=levels_mslp, time=time, projection=projection,
                 cum_hour=cum_hour)

        print_message('Pre-processing finished, launching plotting scripts')
        if debug:
            plot_files(time[1:2], **args)
        else:
            # Parallelize the plotting by dividing into chunks and processes 
            dates = chunks(time, chunks_size)
            plot_files_param=partial(plot_files, **args)
            p = Pool(processes)
            p.map(plot_files_param, dates)
Beispiel #11
0
def eqpt_approx(p, t, q):
    """
    Computes equivalent potential temperature in [K] from pressure,
    temperature and specific humidity.

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

    p, t and q can be scalars or NumPy arrays.

    Returns: equivalent potential temperature in [K].
    """

    return mpcalc.equivalent_potential_temperature(
        units.Pa * p, units.K * t,
        mpcalc.dewpoint_from_specific_humidity(units.Pa * p, units.K * t, q)).to("K").m
Beispiel #12
0
def eqpt_approx(p, t, q):
    """
    Computes equivalent potential temperature in [K] from pressure,
    temperature and specific humidity.

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

    p, t and q can be scalars or NumPy arrays.

    Returns: equivalent potential temperature in [K]. Same dimensions as
    the inputs.
    """
    p = units.Quantity(p, "Pa")
    t = units.Quantity(t, "K")
    dew_temp = mpcalc.dewpoint_from_specific_humidity(p, t, q)
    eqpt_temp = mpcalc.equivalent_potential_temperature(p, t, dew_temp)
    return eqpt_temp.to('K').magnitude
Beispiel #13
0
def main():
    load_start = dt.datetime.now()
    #Try parsing arguments using argparse
    parser = argparse.ArgumentParser(
        description='wrf non-parallel convective diagnostics processer')
    parser.add_argument("-m", help="Model name", required=True)
    parser.add_argument("-r",
                        help="Region name (default is aus)",
                        default="aus")
    parser.add_argument("-t1", help="Time start YYYYMMDDHH", required=True)
    parser.add_argument("-t2", help="Time end YYYYMMDDHH", required=True)
    parser.add_argument(
        "-e",
        help=
        "CMIP5 experiment name (not required if using era5, erai or barra)",
        default="")
    parser.add_argument(
        "--barpa_forcing_mdl",
        help="BARPA forcing model (erai or ACCESS1-0). Default erai.",
        default="erai")
    parser.add_argument(
        "--ens",
        help="CMIP5 ensemble name (not required if using era5, erai or barra)",
        default="r1i1p1")
    parser.add_argument("--group",
                        help="CMIP6 modelling group name",
                        default="")
    parser.add_argument("--project",
                        help="CMIP6 modelling intercomparison project",
                        default="CMIP")
    parser.add_argument("--ver6hr",
                        help="Version on al33 for 6hr data",
                        default="")
    parser.add_argument("--ver3hr",
                        help="Version on al33 for 3hr data",
                        default="")
    parser.add_argument("--issave",
                        help="Save output (True or False, default is False)",
                        default="False")
    parser.add_argument(
        "--ub4",
        help=
        "Where to get era5 data. Default True for ub4 project, otherwise rt52",
        default="True")
    parser.add_argument(
        "--outname",
        help=
        "Name of saved output. In the form *outname*_*t1*_*t2*.nc. Default behaviour is the model name",
        default=None)
    parser.add_argument(
        "--is_dcape",
        help="Should DCAPE be calculated? (1 or 0. Default is 1)",
        default=1)
    parser.add_argument(
        "--al33",
        help=
        "Should data be gathered from al33? Default is False, and data is gathered from r87. If True, then group is required",
        default="False")
    parser.add_argument(
        "--delta_t",
        help=
        "Time step spacing for ERA5 data, in hours. Default is one the minimum spacing (1 hour)",
        default="1")
    parser.add_argument(
        "--era5_interp",
        help=
        "Horizontally interpolate model data before calculating convective parameters",
        default="False")
    args = parser.parse_args()

    #Parse arguments from cmd line and set up inputs (date region model)
    model = args.m
    region = args.r
    t1 = args.t1
    t2 = args.t2
    issave = args.issave
    ub4 = args.ub4
    al33 = args.al33
    if args.outname == None:
        out_name = model
    else:
        out_name = args.outname
    is_dcape = args.is_dcape
    barpa_forcing_mdl = args.barpa_forcing_mdl
    experiment = args.e
    ensemble = args.ens
    group = args.group
    project = args.project
    ver6hr = args.ver6hr
    ver3hr = args.ver3hr
    delta_t = int(args.delta_t)
    era5_interp = args.era5_interp
    if region == "sa_small":
        start_lat = -38
        end_lat = -26
        start_lon = 132
        end_lon = 142
    elif region == "aus":
        start_lat = -44.525
        end_lat = -9.975
        start_lon = 111.975
        end_lon = 156.275
    elif region == "global":
        start_lat = -70
        end_lat = 70
        start_lon = -180
        end_lon = 179.75
    else:
        raise ValueError("INVALID REGION\n")
    domain = [start_lat, end_lat, start_lon, end_lon]
    try:
        time = [
            dt.datetime.strptime(t1, "%Y%m%d%H"),
            dt.datetime.strptime(t2, "%Y%m%d%H")
        ]
    except:
        raise ValueError("INVALID START OR END TIME. SHOULD BE YYYYMMDDHH\n")
    if era5_interp == "True":
        era5_interp = True
    elif era5_interp == "False":
        era5_interp = False
    else:
        raise ValueError("\n INVALID era5_interp...SHOULD BE True OR False")
    if ub4 == "True":
        ub4 = True
    elif ub4 == "False":
        ub4 = False
    else:
        raise ValueError("\n INVALID ub4...SHOULD BE True OR False")
    if issave == "True":
        issave = True
    elif issave == "False":
        issave = False
    else:
        raise ValueError("\n INVALID ISSAVE...SHOULD BE True OR False")
    if al33 == "True":
        al33 = True
    elif al33 == "False":
        al33 = False
    else:
        raise ValueError("\n INVALID al33...SHOULD BE True OR False")

    #Load data
    print("LOADING DATA...")
    if model == "erai":
        ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,\
         cp,tp,wg10,mod_cape,lon,lat,date_list = \
         read_erai(domain,time)
        cp = cp.astype("float32", order="C")
        tp = tp.astype("float32", order="C")
        mod_cape = mod_cape.astype("float32", order="C")
    elif model == "era5":
        if ub4:
            ta,temp1,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,\
             cp,wg10,mod_cape,lon,lat,date_list = \
             read_era5(domain,time,delta_t=delta_t)
        else:
            ta,temp1,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,\
             cp,tp,wg10,mod_cape,lon,lat,date_list = \
             read_era5_rt52(domain,time,delta_t=delta_t)
        cp = cp.astype("float32", order="C")
        tp = tp.astype("float32", order="C")
        mod_cape = mod_cape.astype("float32", order="C")
        wap = np.zeros(hgt.shape)
    elif model == "barra":
        ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,wg10,lon,lat,date_list = \
         read_barra(domain,time)
    elif model == "barra_fc":
        ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,wg10,lon,lat,date_list = \
         read_barra_fc(domain,time)
    elif model == "barpa":
        ta,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,wg10,lon,lat,date_list = \
         read_barpa(domain, time, experiment, barpa_forcing_mdl, ensemble)
        wap = np.zeros(hgt.shape)
        temp1 = None
    elif model == "barra_ad":
        wg10,temp2,ta,temp1,hur,hgt,terrain,p,ps,wap,ua,va,uas,vas,tas,ta2d,lon,lat,date_list = \
         read_barra_ad(domain, time, False)
    elif model in ["ACCESS1-0","ACCESS1-3","GFDL-CM3","GFDL-ESM2M","CNRM-CM5","MIROC5",\
         "MRI-CGCM3","IPSL-CM5A-LR","IPSL-CM5A-MR","GFDL-ESM2G","bcc-csm1-1","MIROC-ESM",\
         "BNU-ESM"]:
        #Check that t1 and t2 are in the same year
        year = np.arange(int(t1[0:4]), int(t2[0:4]) + 1)
        ta, hur, hgt, terrain, p_3d, ps, ua, va, uas, vas, tas, ta2d, tp, lon, lat, \
            date_list = read_cmip(model, experiment, \
            ensemble, year, domain, cmip_ver=5, al33=al33, group=group, ver6hr=ver6hr, ver3hr=ver3hr)
        wap = np.zeros(hgt.shape)
        wg10 = np.zeros(ps.shape)
        mod_cape = np.zeros(ps.shape)
        p = np.zeros(p_3d[0, :, 0, 0].shape)
        #date_list = pd.to_datetime(date_list).to_pydatetime()
        temp1 = None
        tp = tp.astype("float32", order="C")
    elif model in ["ACCESS-ESM1-5", "ACCESS-CM2"]:
        year = np.arange(int(t1[0:4]), int(t2[0:4]) + 1)
        ta, hur, hgt, terrain, p_3d, ps, ua, va, uas, vas, tas, ta2d, lon, lat, \
            date_list = read_cmip(model, experiment,\
            ensemble, year, domain, cmip_ver=6, group=group, project=project)
        wap = np.zeros(hgt.shape)
        wg10 = np.zeros(ps.shape)
        p = np.zeros(p_3d[0, :, 0, 0].shape)
        #date_list = pd.to_datetime(date_list).to_pydatetime()
        temp1 = None
    else:
        raise ValueError("Model not recognised")
    del temp1
    ta = ta.astype("float32", order="C")
    hur = hur.astype("float32", order="C")
    hgt = hgt.astype("float32", order="C")
    terrain = terrain.astype("float32", order="C")
    p = p.astype("float32", order="C")
    ps = ps.astype("float32", order="C")
    wap = wap.astype("float32", order="C")
    ua = ua.astype("float32", order="C")
    va = va.astype("float32", order="C")
    uas = uas.astype("float32", order="C")
    vas = vas.astype("float32", order="C")
    tas = tas.astype("float32", order="C")
    ta2d = ta2d.astype("float32", order="C")
    wg10 = wg10.astype("float32", order="C")
    lon = lon.astype("float32", order="C")
    lat = lat.astype("float32", order="C")

    gc.collect()

    param = np.array([
        "mu_cape", "mu_cin", "muq", "s06", "s0500", "lr700_500", "mhgt",
        "ta500", "tp"
    ])

    if model in ["erai", "era5"]:
        param = np.concatenate([param, ["mod_cape"]])

    #Option to interpolate to the ERA5 grid
    if era5_interp:
        #Interpolate model data to the ERA5 grid
        from era5_read import get_lat_lon_rt52 as get_era5_lat_lon
        era5_lon, era5_lat = get_era5_lat_lon()
        era5_lon_ind = np.where((era5_lon >= domain[2])
                                & (era5_lon <= domain[3]))[0]
        era5_lat_ind = np.where((era5_lat >= domain[0])
                                & (era5_lat <= domain[1]))[0]
        era5_lon = era5_lon[era5_lon_ind]
        era5_lat = era5_lat[era5_lat_ind]
        terrain = interp_era5(terrain, lon, lat, era5_lon, era5_lat, d3=False)
        #Set output array
        output_data = np.zeros(
            (ps.shape[0], era5_lat.shape[0], era5_lon.shape[0], len(param)))
    else:
        output_data = np.zeros(
            (ps.shape[0], ps.shape[1], ps.shape[2], len(param)))

    #Assign p levels to a 3d array, with same dimensions as input variables (ta, hgt, etc.)
    #If the 3d p-lvl array already exists, then declare the variable "mdl_lvl" as true.
    try:
        p_3d
        mdl_lvl = True
        full_p3d = p_3d
    except:
        mdl_lvl = False
        if era5_interp:
            p_3d = np.moveaxis(np.tile(p,[ta.shape[2],ta.shape[3],1]),[0,1,2],[1,2,0]).\
                astype(np.float32)
        else:
            p_3d = np.moveaxis(np.tile(p,[era5_lat.shape[0],era5_lon.shape[0],1]),[0,1,2],[1,2,0]).\
                astype(np.float32)

    print("LOAD TIME..." + str(dt.datetime.now() - load_start))
    tot_start = dt.datetime.now()

    for t in np.arange(0, ta.shape[0]):
        cape_start = dt.datetime.now()

        if era5_interp:
            ta_t = interp_era5(ta[t], lon, lat, era5_lon, era5_lat, d3=True)
            hur_t = interp_era5(hur[t], lon, lat, era5_lon, era5_lat, d3=True)
            hgt_t = interp_era5(hgt[t], lon, lat, era5_lon, era5_lat, d3=True)
            ps_t = interp_era5(ps[t], lon, lat, era5_lon, era5_lat, d3=False)
            wap_t = interp_era5(wap[t], lon, lat, era5_lon, era5_lat, d3=True)
            ua_t = interp_era5(ua[t], lon, lat, era5_lon, era5_lat, d3=True)
            va_t = interp_era5(va[t], lon, lat, era5_lon, era5_lat, d3=True)
            uas_t = interp_era5(uas[t], lon, lat, era5_lon, era5_lat, d3=False)
            vas_t = interp_era5(vas[t], lon, lat, era5_lon, era5_lat, d3=False)
            tas_t = interp_era5(tas[t], lon, lat, era5_lon, era5_lat, d3=False)
            ta2d_t = interp_era5(ta2d[t],
                                 lon,
                                 lat,
                                 era5_lon,
                                 era5_lat,
                                 d3=False)
            tp_t = interp_era5(tp[t], lon, lat, era5_lon, era5_lat, d3=False)
            mod_cape_t = interp_era5(mod_cape[t],
                                     lon,
                                     lat,
                                     era5_lon,
                                     era5_lat,
                                     d3=False)
        else:
            ta_t = ta[t]
            hur_t = hur[t]
            hgt_t = hgt[t]
            ps_t = ps[t]
            wap_t = wap[t]
            ua_t = ua[t]
            va_t = va[t]
            uas_t = uas[t]
            vas_t = vas[t]
            tas_t = tas[t]
            ta2d_t = ta2d[t]
            tp_t = tp[t]
            mod_cape_t = mod_cape[t]
        print(date_list[t])
        output = np.zeros((1, ps_t.shape[0], ps_t.shape[1], len(param)))

        if mdl_lvl:
            if era5_interp:
                p_3d = interp_era5(full_p3d[t],
                                   lon,
                                   lat,
                                   era5_lon,
                                   era5_lat,
                                   d3=True)
            else:
                p_3d = full_p3d[t]

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

        #Insert surface arrays, creating new arrays with "sfc" prefix
        sfc_ta = np.insert(ta_t, 0, tas_t, axis=0)
        sfc_hgt = np.insert(hgt_t, 0, terrain, axis=0)
        sfc_dp = np.insert(dp, 0, ta2d_t, axis=0)
        sfc_p_3d = np.insert(p_3d, 0, ps_t, axis=0)
        sfc_ua = np.insert(ua_t, 0, uas_t, axis=0)
        sfc_va = np.insert(va_t, 0, vas_t, axis=0)
        sfc_wap = np.insert(wap_t, 0, np.zeros(vas_t.shape), axis=0)

        #Sort by ascending p
        a,temp1,temp2 = np.meshgrid(np.arange(sfc_p_3d.shape[0]) , np.arange(sfc_p_3d.shape[1]),\
          np.arange(sfc_p_3d.shape[2]))
        sort_inds = np.flip(np.lexsort([np.swapaxes(a, 1, 0), sfc_p_3d],
                                       axis=0),
                            axis=0)
        sfc_hgt = np.take_along_axis(sfc_hgt, sort_inds, axis=0)
        sfc_dp = np.take_along_axis(sfc_dp, sort_inds, axis=0)
        sfc_p_3d = np.take_along_axis(sfc_p_3d, sort_inds, axis=0)
        sfc_ua = np.take_along_axis(sfc_ua, sort_inds, axis=0)
        sfc_va = np.take_along_axis(sfc_va, sort_inds, axis=0)
        sfc_ta = np.take_along_axis(sfc_ta, sort_inds, axis=0)

        #Calculate q and wet bulb for pressure level arrays with surface values
        sfc_ta_unit = units.units.degC * sfc_ta
        sfc_dp_unit = units.units.degC * sfc_dp
        sfc_p_unit = units.units.hectopascals * sfc_p_3d
        hur_unit = mpcalc.relative_humidity_from_dewpoint(ta_t*units.units.degC, dp*units.units.degC)*\
         100*units.units.percent
        q_unit = mpcalc.mixing_ratio_from_relative_humidity(hur_unit,\
         ta_t*units.units.degC,np.array(p_3d)*units.units.hectopascals)
        sfc_hur_unit = mpcalc.relative_humidity_from_dewpoint(sfc_ta_unit, sfc_dp_unit)*\
         100*units.units.percent
        sfc_q_unit = mpcalc.mixing_ratio_from_relative_humidity(sfc_hur_unit,\
         sfc_ta_unit,sfc_p_unit)
        sfc_theta_unit = mpcalc.potential_temperature(sfc_p_unit, sfc_ta_unit)
        sfc_thetae_unit = mpcalc.equivalent_potential_temperature(
            sfc_p_unit, sfc_ta_unit, sfc_dp_unit)
        sfc_thetae = np.array(mpcalc.equivalent_potential_temperature(ps_t*units.units.hectopascals,tas_t*units.units.degC,\
              ta2d_t*units.units.degC))
        sfc_q = np.array(sfc_q_unit)
        sfc_hur = np.array(sfc_hur_unit)
        #sfc_wb = np.array(wrf.wetbulb( sfc_p_3d*100, sfc_ta+273.15, sfc_q, units="degC"))

        #Use getcape.f90
        #cape_gb_mu1, cape_gb_mu4 = getcape_driver(sfc_p_3d, sfc_ta, sfc_dp, ps_t)

        #Now get most-unstable CAPE (max CAPE in vertical, ensuring parcels used are AGL)
        cape3d = wrf.cape_3d(sfc_p_3d,sfc_ta+273.15,\
          sfc_q,sfc_hgt,\
          terrain,ps_t,\
          True,meta=False, missing=0)
        cape = cape3d.data[0]
        cin = cape3d.data[1]
        lfc = cape3d.data[2]
        lcl = cape3d.data[3]
        el = cape3d.data[4]
        #Mask values which are below the surface and above 350 hPa AGL
        cape[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan
        cin[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan
        lfc[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan
        lcl[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan
        el[(sfc_p_3d > ps_t) | (sfc_p_3d < (ps_t - 350))] = np.nan
        #Get maximum (in the vertical), and get cin, lfc, lcl for the same parcel
        mu_cape_inds = np.tile(np.nanargmax(cape, axis=0),
                               (cape.shape[0], 1, 1))
        mu_cape = np.take_along_axis(cape, mu_cape_inds, 0)[0]
        mu_cin = np.take_along_axis(cin, mu_cape_inds, 0)[0]
        mu_lfc = np.take_along_axis(lfc, mu_cape_inds, 0)[0]
        mu_lcl = np.take_along_axis(lcl, mu_cape_inds, 0)[0]
        mu_el = np.take_along_axis(el, mu_cape_inds, 0)[0]
        muq = np.take_along_axis(sfc_q, mu_cape_inds, 0)[0] * 1000

        #Calculate other parameters
        #Thermo
        thermo_start = dt.datetime.now()
        lr700_500 = get_lr_p(ta_t, p_3d, hgt_t, 700, 500)
        melting_hgt = get_t_hgt(sfc_ta, np.copy(sfc_hgt), 0, terrain)
        melting_hgt = np.where((melting_hgt < 0) | (np.isnan(melting_hgt)), 0,
                               melting_hgt)
        ta500 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 500)
        ta925 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 925)
        ta850 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 850)
        ta700 = get_var_p_lvl(np.copy(sfc_ta), sfc_p_3d, 700)
        rho = mpcalc.density(
            np.array(sfc_p_3d) * (units.units.hectopascal),
            sfc_ta * units.units.degC, sfc_q_unit)
        rho925 = np.array(get_var_p_lvl(np.array(rho), sfc_p_3d, 925))
        rho850 = np.array(get_var_p_lvl(np.array(rho), sfc_p_3d, 850))
        rho700 = np.array(get_var_p_lvl(np.array(rho), sfc_p_3d, 700))
        #Winds
        winds_start = dt.datetime.now()
        s06 = get_shear_hgt(sfc_ua, sfc_va, np.copy(sfc_hgt), 0, 6000, terrain)
        s0500 = get_shear_p(ua_t,
                            va_t,
                            p_3d,
                            "sfc",
                            np.array([500]),
                            p_3d,
                            uas=uas_t,
                            vas=vas_t)[0]

        #WAP
        if model in ["erai", "era5"]:
            sfc_w = mpcalc.vertical_velocity( wap_t * (units.units.pascal / units.units.second),\
             np.array(p_3d) * (units.units.hectopascal), \
             ta_t * units.units.degC,  q_unit)
            w925 = np.array(get_var_p_lvl(np.array(sfc_w), p_3d, 925))
            w850 = np.array(get_var_p_lvl(np.array(sfc_w), p_3d, 850))
            w700 = np.array(get_var_p_lvl(np.array(sfc_w), p_3d, 700))

        #Convergence
        if era5_interp:
            x, y = np.meshgrid(era5_lon, era5_lat)
        else:
            x, y = np.meshgrid(lon, lat)
        dx, dy = mpcalc.lat_lon_grid_deltas(x, y)
        u925 = np.array(get_var_p_lvl(np.copy(sfc_ua), sfc_p_3d, 925))
        u850 = np.array(get_var_p_lvl(np.copy(sfc_ua), sfc_p_3d, 850))
        u700 = np.array(get_var_p_lvl(np.copy(sfc_ua), sfc_p_3d, 700))
        v925 = np.array(get_var_p_lvl(np.copy(sfc_va), sfc_p_3d, 925))
        v850 = np.array(get_var_p_lvl(np.copy(sfc_va), sfc_p_3d, 850))
        v700 = np.array(get_var_p_lvl(np.copy(sfc_va), sfc_p_3d, 700))
        conv925 = -1e5 * np.array(
            mpcalc.divergence(u925 * (units.units.meter / units.units.second),
                              v925 * (units.units.meter / units.units.second),
                              dx, dy))
        conv850 = -1e5 * np.array(
            mpcalc.divergence(u850 * (units.units.meter / units.units.second),
                              v850 * (units.units.meter / units.units.second),
                              dx, dy))
        conv700 = -1e5 * np.array(
            mpcalc.divergence(u700 * (units.units.meter / units.units.second),
                              v700 * (units.units.meter / units.units.second),
                              dx, dy))

        #CS6
        mucs6 = mu_cape * np.power(s06, 1.67)

        #Fill output
        output = fill_output(output, t, param, ps, "mu_cape", mu_cape)
        output = fill_output(output, t, param, ps, "mu_cin", mu_cin)
        output = fill_output(output, t, param, ps, "muq", muq)
        output = fill_output(output, t, param, ps, "s06", s06)
        output = fill_output(output, t, param, ps, "s0500", s0500)
        output = fill_output(output, t, param, ps, "lr700_500", lr700_500)
        output = fill_output(output, t, param, ps, "ta500", ta500)
        output = fill_output(output, t, param, ps, "mhgt", melting_hgt)
        output = fill_output(output, t, param, ps, "tp", tp_t)
        if (model == "erai") | (model == "era5"):
            output = fill_output(output, t, param, ps, "mod_cape", mod_cape_t)

        output_data[t] = output

    print("SAVING DATA...")
    param_out = []
    for param_name in param:
        temp_data = output_data[:, :, :, np.where(param == param_name)[0][0]]
        param_out.append(temp_data)

    #If the mhgt variable is zero everywhere, then it is likely that data has not been read.
    #In this case, all values are missing, set to zero.
    for t in np.arange(param_out[0].shape[0]):
        if param_out[np.where(param == "mhgt")[0][0]][t].max() == 0:
            for p in np.arange(len(param_out)):
                param_out[p][t] = np.nan

    if issave:
        if era5_interp:
            save_netcdf(region, model, out_name, date_list, era5_lat, era5_lon, param, param_out, \
             out_dtype = "f4", compress=True)
        else:
            save_netcdf(region, model, out_name, date_list, lat, lon, param, param_out, \
             out_dtype = "f4", compress=True)

    print(dt.datetime.now() - tot_start)
Beispiel #14
0
def test_equivalent_potential_temperature():
    """Test equivalent potential temperature calculation."""
    p = 999. * units.mbar
    t = 288. * units.kelvin
    ept = equivalent_potential_temperature(p, t)
    assert_almost_equal(ept, 315.9548 * units.kelvin, 3)
if __name__ == '__main__':

    temp = [0, 5, 10, 15, 20, 25]
    rh = [100, 100, 100, 100, 100, 100]
    pres = [850, 850, 850, 850, 850, 850]

    df = pd.DataFrame({'Temp.': temp, 'Humidity': rh, 'Pressure': pres})
    print(df)

    print(df['Temp.'].values * units('deg'))
    print(df['Humidity'].values / 100.)
    print(df['Pressure'].values * 100.)

    # 露点温度の算出
    dewpoint = dewpoint_from_relative_humidity(
        (df['Temp.'].values * units('degC')).to(units('K')),
        df['Humidity'].values / 100.)
    print('##### 露点温度 #####')
    print(dewpoint)
    print(dewpoint.to(units('K')))

    # 相当温位の算出
    potensial_temp = equivalent_potential_temperature(
        df['Pressure'].values * units('hPa'),
        (df['Temp.'].values * units('degC')).to(units('K')),
        dewpoint.to(units('K')))
    print('##### 相当温位 #####')
    print(potensial_temp)

    #        'dewpoint': dewpoint_rh( (np.array(temp) * units('degC') ).to(units('K') ),
    #                            np.array(rh) / 100.).to(units('degF')),
Beispiel #16
0
def getData(model, station, time, fileExport=False, exportPath=''):

    df = getDataFrame_UpperAir(model, station, time, 0)

    try:  # Verify data found
        df.head
        print(f'Reading {model} profile for {station} valid {time}')
    except:
        print(
            f'ERROR reading {model} profile for {station} valid {time}. No data found'
        )
        return None

    if station == 'LO1':
        plot = SkewT.drawSkewT([model, time, 0, station, df], 10, 10, 100,
                               True, 250, True, False, False, True, True)
        plotPath = exportPath.replace('data/BUFKIT', 'plots/SkewT')
        plotPath = plotPath.replace(
            '.csv',
            time.strftime("_SkewT_%Y%m%d_%H%M") + '.png')
        plot.savefig(plotPath, bbox_inches='tight')

    pblHeight = 0
    dgzLayer = [-999, -999]
    desiredLevels = [[925.00 * units.hPa, False], [850.00 * units.hPa, False],
                     [700.00 * units.hPa, False], [500.00 * units.hPa, False]]

    dataString = f'{model},{station},{time}'

    z = df['height'].values
    p = df['pressure'].values
    T = df['temperature'].values
    Td = df['dewpoint'].values
    theta = df['theta'].values
    theta_e = df['theta_e'].values
    u = df['u_wind'].values
    v = df['v_wind'].values

    for i in range(len(z)):

        if i > 0:

            # Calculate temperature lapse-rate
            dT = T[i] - T[i - 1]
            dz = (z[i] - z[i - 1]).to('km')
            dT_dz = dT / dz

            # Calculate dewpoint lapse-rate
            dTd = Td[i] - Td[i - 1]
            dTd_dz = dTd / dz

            # Calculate potential temperature lapse-rate
            thetaLwr = mpcalc.potential_temperature(p[i - 1], T[i - 1])
            thetaUpr = mpcalc.potential_temperature(p[i], T[i])
            dTheta_dz = (thetaUpr - thetaLwr) / dz

            # Calculate equivalent potential temperature lapse-rate
            theta_eLwr = mpcalc.equivalent_potential_temperature(
                p[i - 1], T[i - 1], Td[i - 1])
            theta_eUpr = mpcalc.equivalent_potential_temperature(
                p[i], T[i], Td[i])
            dThetaE_dz = (theta_eUpr - theta_eLwr) / dz

            #print(p[i], z[i], dT_dz, dTd_dz, dTheta_dz, dThetaE_dz)

            # Find PBL height
            # Look for where (dT/dz >= -9.8 and dθ/dz >= 0) or (dθ/dz >= 0.0 and dθ-e/dz >= 2)
            if (((dT_dz.magnitude >= -5.7) and (dTheta_dz.magnitude >= 0.0)) or
                ((dTheta_dz.magnitude >= 0.0) and
                 (dThetaE_dz.magnitude >= 2.0))) and pblHeight == 0:
                pblHeight = z[i]
                #print('*****', p[i], z[i], dT_dz, dTheta_dz, dThetaE_dz)

            # Find DGZ layer
            if (-18.0 <= T[i].magnitude <= -12.0):
                # Update lower bound if not set
                if dgzLayer[0] == -999:
                    dgzLayer[0] = p[i]
                # Update upper bound
                dgzLayer[1] = p[i]

            # Extract values at desired levels
            for dataLevel in desiredLevels:
                if (p[i - 1] >= dataLevel[0]) and (
                        p[i] <= dataLevel[0]) and dataLevel[1] == False:

                    # Interpolate values to data level
                    tmpc = LinearInterpolation(dataLevel[0], p[i - 1], p[i],
                                               T[i - 1], T[i])
                    dwpc = LinearInterpolation(dataLevel[0], p[i - 1], p[i],
                                               Td[i - 1], Td[i])
                    hght = LinearInterpolation(dataLevel[0], p[i - 1], p[i],
                                               z[i - 1], z[i])

                    # RH from dewpoint
                    relh = mpcalc.relative_humidity_from_dewpoint(
                        tmpc, dwpc).to('percent')

                    # Calculate wind vector and interpolate values to data level
                    uwnd = LinearInterpolation(dataLevel[0], p[i - 1], p[i],
                                               u[i - 1], u[i])
                    vwnd = LinearInterpolation(dataLevel[0], p[i - 1], p[i],
                                               v[i - 1], v[i])

                    # Wind speed/direction from u,v
                    drct = mpcalc.wind_direction(uwnd, vwnd)
                    sknt = mpcalc.wind_speed(uwnd, vwnd)

                    # Output values
                    dataString += f',{round(hght.magnitude, 2)},{round(tmpc.magnitude, 2)},{round(relh.magnitude, 2)},{round(uwnd.magnitude, 2)},{round(vwnd.magnitude, 2)}'
                    dataLevel[1] = True

            # Derived quantities
            #dataString+=f',{round(pblHeight.magnitude, 2)}'

        # Go to next level
        i += 1

    # Export to file
    if fileExport and exportPath != '':
        file = open(exportPath, 'a+')
        file.write(dataString + '\n')
        file.close()

    dataString = ''
def metpy_read_wrf_cross(fname, plevels, tidx_in, lons_out, lats_out, start,
                         end):

    ds = xr.open_dataset(fname).metpy.parse_cf().squeeze()
    ds = ds.isel(Time=tidx)
    print(ds)

    ds1 = xr.Dataset()

    p = units.Quantity(to_np(ds.p), 'hPa')
    z = units.Quantity(to_np(ds.z), 'meter')
    u = units.Quantity(to_np(ds.u), 'm/s')
    v = units.Quantity(to_np(ds.v), 'm/s')
    w = units.Quantity(to_np(ds.w), 'm/s')
    tk = units.Quantity(to_np(ds.tk), 'kelvin')
    th = units.Quantity(to_np(ds.th), 'kelvin')
    eth = units.Quantity(to_np(ds.eth), 'kelvin')
    wspd = units.Quantity(to_np(ds.wspd), 'm/s')
    omega = units.Quantity(to_np(ds.omega), 'Pa/s')

    plevels_unit = plevels * units.hPa
    z, u, v, w, tk, th, eth, wspd, omega = log_interpolate_1d(plevels_unit,
                                                              p,
                                                              z,
                                                              u,
                                                              v,
                                                              w,
                                                              tk,
                                                              th,
                                                              eth,
                                                              wspd,
                                                              omega,
                                                              axis=0)

    coords, dims = [plevs, ds.lat.values,
                    ds.lon.values], ["level", "lat", "lon"]
    for name, var in zip(
        ['z', 'u', 'v', 'w', 'tk', 'th', 'eth', 'wspd', 'omega'],
        [z, u, v, w, tk, th, eth, wspd, omega]):
        #g = ndimage.gaussian_filter(var, sigma=3, order=0)
        ds1[name] = xr.DataArray(to_np(mpcalc.smooth_n_point(var, 9)),
                                 coords=coords,
                                 dims=dims)

    dx, dy = mpcalc.lat_lon_grid_deltas(ds.lon.values * units('degrees_E'),
                                        ds.lat.values * units('degrees_N'))

    # Calculate temperature advection using metpy function
    for i, plev in enumerate(plevs):

        adv = mpcalc.advection(eth[i, :, :], [u[i, :, :], v[i, :, :]],
                               (dx, dy),
                               dim_order='yx') * units('K/sec')
        adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec')
        ds1['eth_adv_{:03d}'.format(plev)] = xr.DataArray(
            np.array(adv),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

        div = mpcalc.divergence(u[i, :, :], v[i, :, :], dx, dy, dim_order='yx')
        div = ndimage.gaussian_filter(div, sigma=3, order=0) * units('1/sec')
        ds1['div_{:03d}'.format(plev)] = xr.DataArray(
            np.array(div),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

    ds1['accrain'] = xr.DataArray(ds.accrain.values,
                                  coords=[ds.lat.values, ds.lon.values],
                                  dims=["lat", "lon"])
    eth2 = mpcalc.equivalent_potential_temperature(
        ds.slp.values * units.hPa, ds.t2m.values * units('K'),
        ds.td2.values * units('celsius'))
    ds1['eth2'] = xr.DataArray(eth2,
                               coords=[ds.lat.values, ds.lon.values],
                               dims=["lat", "lon"])
    #ds1['sst'] = xr.DataArray(ndimage.gaussian_filter(ds.sst.values, sigma=3, order=0)-273.15, coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"])
    ds1 = ds1.metpy.parse_cf().squeeze()

    cross = cross_section(ds1, start, end).set_coords(('lat', 'lon'))
    cross.u.attrs['units'] = 'm/s'
    cross.v.attrs['units'] = 'm/s'

    cross['t_wind'], cross['n_wind'] = mpcalc.cross_section_components(
        cross['u'], cross['v'])

    weights = np.cos(np.deg2rad(ds.lat))
    ds_weighted = ds.weighted(weights)
    weighted = ds_weighted.mean(("lat"))

    return ds1, cross, weighted
Beispiel #18
0
                            dim_order='yx') * units('K/sec')
PT850 = mpcalc.potential_temperature(850 * units.mbar, T850)
FRONT_850 = mpcalc.frontogenesis(PT850, U850, V850, DX, DY, dim_order='YX')
# =============================================================================
# FIG #5: 850: GEOPOTENTIAL HEIGHT, EQUIV. POT. TEMP, WINDS, LAPSE RATES
# =============================================================================
H500 = HGT_DATA.variables['hgt'][TIME_INDEX, 5, :, :]
H700 = HGT_DATA.variables['hgt'][TIME_INDEX, 3, :, :]
T500 = AIR_DATA.variables['air'][TIME_INDEX, 5, :, :] * units('degC')
T700 = AIR_DATA.variables['air'][TIME_INDEX, 3, :, :] * units('degC')
LR = -1000 * (T500 - T700) / (H500 - H700)
H850 = HGT_DATA.variables['hgt'][TIME_INDEX, 2, :, :]
T850 = AIR_DATA.variables['air'][TIME_INDEX, 2, :, :] * units('kelvin')
SH850 = SHUM_DATA.variables['shum'][TIME_INDEX, 2, :, :]
DP850 = mpcalc.dewpoint_from_specific_humidity(SH850, T850, 850 * units.mbar)
EPT850 = mpcalc.equivalent_potential_temperature(850 * units.mbar, T850, DP850)
# =============================================================================
# FIG #6: 925: MOISTURE FLUX, MOISTURE FLUX CONVERGENCE,
# =============================================================================
RH925 = HUM_DATA.variables['rhum'][TIME_INDEX, 1, :, :]
SH925 = SHUM_DATA.variables['shum'][TIME_INDEX, 1, :, :]
U925 = UWND_DATA.variables['uwnd'][TIME_INDEX, 1, :, :] * units('m/s')
V925 = VWND_DATA.variables['vwnd'][TIME_INDEX, 1, :, :] * units('m/s')
H925 = HGT_DATA.variables['hgt'][TIME_INDEX, 1, :, :]
SH_ADV925 = mpcalc.advection(SH925, [U925, V925], (DX, DY), dim_order='yx')
SH_DIV925 = SH925 * (mpcalc.divergence(U925, V925, DX, DY, dim_order='YX'))
MFLUXX = SH925 * U925
MFLUXY = SH925 * V925
MFC_925 = SH_ADV925 + SH_DIV925
# =============================================================================
# FIG #7: SFC: MSLP, WIND, TEMPERATURE
Beispiel #19
0
 def process_skewt(self):
     # Calculation
     index_p100 = get_pressure_level_index(self.p_i, 100)
     lcl_p, lcl_t = mpcalc.lcl(self.p_i[0], self.t_i[0], self.td_i[0])
     lfc_p, lfc_t = mpcalc.lfc(self.p_i, self.t_i, self.td_i)
     el_p, el_t = mpcalc.el(self.p_i, self.t_i, self.td_i)
     prof = mpcalc.parcel_profile(self.p_i, self.t_i[0], self.td_i[0]).to('degC')
     cape, cin = mpcalc.cape_cin(self.p_i, self.t_i, self.td_i, prof)
     mucape, mucin = mpcalc.most_unstable_cape_cin(self.p_i, self.t_i, self.td_i)
     pwat = mpcalc.precipitable_water(self.td_i, self.p_i)
     i8 = get_pressure_level_index(self.p_i, 850)
     i7 = get_pressure_level_index(self.p_i, 700)
     i5 = get_pressure_level_index(self.p_i, 500)
     theta850 = mpcalc.equivalent_potential_temperature(850 * units('hPa'), self.t_i[i8], self.td_i[i5])
     theta500 = mpcalc.equivalent_potential_temperature(500 * units('hPa'), self.t_i[i5], self.td_i[i5])
     thetadiff = theta850 - theta500
     k = self.t_i[i8] - self.t_i[i5] + self.td_i[i8] - (self.t_i[i7] - self.td_i[i7])
     a = ((self.t_i[i8] - self.t_i[i5]) - (self.t_i[i8] - self.td_i[i5]) -
         (self.t_i[i7] - self.td_i[i7]) - (self.t_i[i5] - self.td_i[i5]))
     sw = c_sweat(np.array(self.t_i[i8].magnitude), np.array(self.td_i[i8].magnitude),
                  np.array(self.t_i[i5].magnitude), np.array(self.u_i[i8].magnitude),
                  np.array(self.v_i[i8].magnitude), np.array(self.u_i[i5].magnitude),
                  np.array(self.v_i[i5].magnitude))
     si = showalter_index(self.t_i[i8], self.td_i[i8], self.t_i[i5])
     li = lifted_index(self.t_i[0], self.td_i[0], self.p_i[0], self.t_i[i5])
     srh_pos, srh_neg, srh_tot = mpcalc.storm_relative_helicity(self.u_i, self.v_i, self.alt, 1000 * units('m'))
     sbcape, sbcin = mpcalc.surface_based_cape_cin(self.p_i, self.t_i, self.td_i)
     shr6km = mpcalc.bulk_shear(self.p_i, self.u_i, self.v_i, heights=self.alt, depth=6000 * units('m'))
     wshr6km = mpcalc.wind_speed(*shr6km)
     sigtor = mpcalc.significant_tornado(sbcape, delta_height(self.p_i[0], lcl_p), srh_tot, wshr6km)[0]
     # Plotting
     self.ax.set_ylim(1050, 100)
     self.ax.set_xlim(-40, 50)
     self.plot(self.p_i, self.t_i, 'r', linewidth=1)
     self.plot(self.p_i[:self.dp_idx], self.td_i[:self.dp_idx], 'g', linewidth=1)
     self.plot_barbs(self.p_i[:index_p100], self.u_i[:index_p100] * 1.94, self.v_i[:index_p100] * 1.94)
     self.plot(lcl_p, lcl_t, 'ko', markerfacecolor='black')
     self.plot(self.p_i, prof, 'k', linewidth=2)
     if cin.magnitude < 0:
         chi = -1 * cin.magnitude
         self.shade_cin(self.p_i, self.t_i, prof)
     elif cin.magnitude > 0:
         chi = cin.magnitude
         self.shade_cin(self.p_i, self.t_i, prof)
     else:
         chi = 0.
     self.shade_cape(self.p_i, self.t_i, prof)
     self.plot_dry_adiabats(linewidth=0.5)
     self.plot_moist_adiabats(linewidth=0.5)
     self.plot_mixing_lines(linewidth=0.5)
     plt.title('Skew-T Plot \nStation: {} Time: {}'.format(self.st, self.time.strftime('%Y.%m.%d %H:%M')), fontsize=14, loc='left')
     # Add hodograph
     ax = self._fig.add_axes([0.95, 0.71, 0.17, 0.17])
     h = Hodograph(ax, component_range=50)
     h.add_grid(increment=20)
     h.plot_colormapped(self.u_i[:index_p100], self.v_i[:index_p100], self.alt[:index_p100], linewidth=1.2)
     # Annotate parameters
     # Annotate names
     namelist = ['CAPE', 'CIN', 'MUCAPE', 'PWAT', 'K', 'A', 'SWEAT', 'LCL', 'LFC', 'EL', 'SI', 'LI', 'T850-500',
                 'θse850-500', 'SRH', 'STP']
     xcor = -50
     ycor = -90
     spacing = -9
     for nm in namelist:
         ax.text(xcor, ycor, '{}: '.format(nm), fontsize=10)
         ycor += spacing
     # Annotate values
     varlist = [cape, chi, mucape, pwat, k, a, sw, lcl_p, lfc_p, el_p, si, li, self.t_i[i8] - self.t_i[i5], thetadiff,
                srh_tot, sigtor]
     xcor = 10
     ycor = -90
     for v in varlist:
         if hasattr(v, 'magnitude'):
             v = v.magnitude
         ax.text(xcor, ycor, str(np.round_(v, 2)), fontsize=10)
         ycor += spacing
     # Annotate units
     unitlist = ['J/kg', 'J/kg', 'J/kg', 'mm', '°C', '°C', '', 'hPa', 'hPa', 'hPa', '°C', '°C', '°C', '°C']
     xcor = 45
     ycor = -90
     for u in unitlist:
         ax.text(xcor, ycor, ' {}'.format(u), fontsize=10)
         ycor += spacing
Beispiel #20
0
    def jp_850_eptw(self, path):  # 850hPa相当温位/風(日本域)

        path_fig = os.path.join(path, self.time_str1 + '.jpg')
        if (os.path.exists(path_fig)): return
        # 850hPa気温の取得
        temp, lat, lon = self.grib2_select_jp('t', 850)
        temp = temp * units.kelvin
        # 850hPa風の取得
        wind_u, _, _ = self.grib2_select_jp('u', 850) * units('m/s')
        wind_v, _, _ = self.grib2_select_jp('v', 850) * units('m/s')
        # 850hPa相対湿度の取得
        rh, _, _ = self.grib2_select_jp('r', 850)
        rh *= 0.01
        # 露点温度の計算
        dewp = mpcalc.dewpoint_from_relative_humidity(temp, rh)
        # 相当温位の計算
        ept = mpcalc.equivalent_potential_temperature(850 * units.hPa, temp,
                                                      dewp)
        ept = gaussian_filter(ept, sigma=1.0)
        # 地図の描画
        fig, ax = self.draw_map(self.mapcrs_jp, self.extent_jp)
        # 等温線を引く
        ept_arange = np.arange(255, 372, 3)
        ept_constant = ax.contourf(lon,
                                   lat,
                                   ept,
                                   ept_arange,
                                   extend='both',
                                   cmap='jet',
                                   transform=self.datacrs,
                                   alpha=0.9)
        ept_line = ax.contour(lon,
                              lat,
                              ept,
                              ept_arange,
                              colors='black',
                              linestyles='solid',
                              linewidths=1,
                              transform=self.datacrs)
        plt.clabel(ept_line,
                   levels=np.arange(258, 372, 6),
                   fmt='%d',
                   fontsize=self.fontsize)
        # カラーバーをつける
        cbar = self.draw_jp_colorbar(ept_constant)
        cbar.set_label('E.P.TEMP(K)', fontsize=self.fontsize)
        # 風ベクトルの表示
        wind_arrow = (slice(None, None, 5), slice(None, None, 5))
        ax.barbs(lon[wind_arrow],
                 lat[wind_arrow],
                 wind_u[wind_arrow].to('kt').m,
                 wind_v[wind_arrow].to('kt').m,
                 pivot='middle',
                 length=8,
                 color='black',
                 alpha=0.5,
                 transform=self.datacrs)
        # タイトルをつける
        self.draw_title(ax, '850hPa: E.P.TEMP(K), WIND ARROW(kt)',
                        self.time_str2)
        # 大きさの調整
        plt.subplots_adjust(bottom=0.05, top=0.95, left=0, right=1.0)
        # 保存
        print(f'[{self.time_str2}] 850hPa相当温位/風(日本域)...{path_fig}'.format())
        plt.savefig(path_fig)
        # 閉じる
        plt.close(fig=fig)
Beispiel #21
0
def read_TInsitu(pname, print_long, e_test, tstart=None, tend=None, d_testing=False):
    ''' Reads data files provided on TORUS19 EOL site (Important that datafiles and filenames follow TORUS19 readme)
        ---
        INPUT: filename string (following readme conventions for each platform)
               tstart,tend: datetime objects
        OUTPUT: dataframe containing all data collected during desired times
    '''
    if pname in pform_names('UNL'):
        mmfile = glob.glob(config.g_mesonet_directory+config.day+'/mesonets/UNL/UNL.'+pname+'.*')

        # Test Data availability
        if d_testing == True:
            try:
                #if there is no files this will will cause the try statement to fail
                mtest = mmfile[0]
                return True
            except: return False
        #  if the defn was only called to it will exit at this point (saving computing time)
        # + + + + + + + + + + + + ++ + +

        data_hold = [] #empty list to append to
        for i in range(len(mmfile)):
            ds = xr.open_dataset(mmfile[i])

            #convert form epoch time to utc datetime object
            timearray = np.array([dt.datetime.utcfromtimestamp(t/1e9) for t in ds.time.values])
            U,V = mpcalc.wind_components(ds.wind_speed, ds.wind_dir)
            lats = np.array([40]) * units.degrees

            #create new xarray dataset to make plotting easier cause original is trash
            dims = ['datetime']
            coords = { 'datetime': timearray }
            data_vars = {
                'lat': (dims, ds.lat.values, {'units':str(lats.units)}),
                'lon': (dims, ds.lon.values, {'units':str(lats.units)}),
                'Z_ASL': (dims, ds.alt.values, {'units':str(ds.alt.units)}),
                'Z_AGL': (dims, np.zeros_like(ds.alt.values), {'units':str(ds.alt.units)}),
                'Temperature': (dims, ds.fast_temp.values, {'units':str(ds.fast_temp.units)}),
                'Dewpoint': (dims, ds.dewpoint.values, {'units':str(ds.dewpoint.units)}),
                'RH': (dims, ds.calc_corr_RH.values, {'units':str(ds.calc_corr_RH.units)}),
                'Pressure': (dims, ds.pressure.values, {'units':str(ds.pressure.units)}),
                'U': (dims, U.m, {'units':str(U.units)}),
                'V': (dims, V.m, {'units':str(V.units)}),
                'Theta': (dims, ds.theta.values, {'units':str(ds.theta.units)}),
                'Thetae': (dims, ds.theta_e.values, {'units':str(ds.theta_e.units)}),
                'Thetav': (dims, ds.theta_v.values, {'units':str(ds.theta_v.units)})
            }

            subds = xr.Dataset(data_vars, coords)

            #convert to pandas
            pd_unl = subds.to_dataframe()
            pd_unl.reset_index(inplace=True)

            # Subset the dataset to the desired 22:43
            if tstart is None: hstart = pd_unl['datetime'].iloc[0]
            else: hstart = tstart
            if tend is None: hend = pd_unl['datetime'].iloc[-1]
            else: hend = tend
            # Save only desired iop data
            data_u = pd_unl.loc[(pd_unl['datetime'] >= hstart) & (pd_unl['datetime'] <= hend)]
            data_hold.append(data_u)

        #convert the list holding the dataframes to one large dataframe
        data_unl = pd.concat(data_hold)

        #drop all the columns that we will not use past this point (to save memory/computing time)
        data_unl = data_unl.drop(columns=['Temperature', 'Z_ASL', 'Z_AGL', 'Theta', 'Dewpoint', 'Pressure', 'RH'])
        #  print(data_unl.memory_usage())
        #  data_unl.set_index('datetime', inplace=True, drop=False)
        return data_unl, 'UNL'

    # * * *
    elif pname in pform_names('NSSL'):
        mmfile = glob.glob(config.g_mesonet_directory+config.day+'/mesonets/NSSL/'+pname+'_'+config.day[2:]+'_QC_met.dat')

        # Test Data availability
        if d_testing == True:
            try:
                #if there is no files this will will cause the try statement to fail
                mtest = mmfile[0]
                return True
            except: return False
        # + + + + + + + + + + + + ++ + +

        mmfile=mmfile[0]
        # Read NSSL file using column names from readme
        column_names = ['id','time','lat','lon','alt','tfast','tslow','rh','p','dir','spd','qc1','qc2','qc3','qc4']
        data = pd.read_csv(mmfile, header=0, delim_whitespace=True, names=column_names)
        data = data.drop_duplicates()

        # Find timedelta of hours since start of iop (IOP date taken from filename!)
        tiop = dt.datetime(2019, np.int(mmfile[-15:-13]), np.int(mmfile[-13:-11]), 0, 0, 0)

        if tstart is None:
            hstart = tiop
            hstart_dec = hstart.hour + (hstart.minute/60) + (hstart.second/3600) #convert to decimal hours HH.HHH
        else:
            hstart = float((tstart - tiop).seconds)/3600
            hstart_dec = hstart

        if tend is None:
            hend = data['time'].iloc[-1]
        else:
            hend = (tend - tiop)
            if hend >= dt.timedelta(days=1): hend = float((tend-tiop).seconds)/3600 + 24.
            else: hend = float((tend-tiop)).seconds/3600

        # Save only desired iop data
        data_nssl = data.loc[(data['time'] >= hstart_dec) & (data['time'] <= hend)]
        # Convert time into timedeltas
        date = dt.datetime.strptime('2019-'+mmfile[-15:-13]+'-'+mmfile[-13:-11],'%Y-%m-%d')
        time_deltas = []
        for i in np.arange(len(data_nssl)):
            j = data_nssl['time'].iloc[i]
            time_deltas = np.append(time_deltas, date + dt.timedelta(hours=int(j), minutes=int((j*60) % 60), seconds=int((j*3600) % 60)))
        data_nssl['datetime'] = time_deltas

        ## Caclulate desired variables
        p, t = data_nssl['p'].values * units.hectopascal, data_nssl['tfast'].values * units.degC
        r_h = data_nssl['rh'].values/100
        data_nssl['Theta'] = (mpcalc.potential_temperature(p, t)).m

        mixing = mpcalc.mixing_ratio_from_relative_humidity(r_h, t, p)
        data_nssl['Thetav'] = (mpcalc.virtual_potential_temperature(p, t, mixing)).m

        td = mpcalc.dewpoint_rh(temperature= t, rh= r_h)
        data_nssl['Thetae'] = (mpcalc.equivalent_potential_temperature(p, t, td)).m

        Spd, dire = data_nssl['spd'].values * units('m/s') , data_nssl['dir'].values * units('degrees')
        u, v = mpcalc.wind_components(Spd, dire)
        data_nssl['U'], data_nssl['V'] = u.to('knot'), v.to('knot')

        #  q_list = ['qc1','qc2','qc3','qc4']
        q_list = config.NSSL_qcflags
        data_nssl['all_qc_flags'] = data_nssl[q_list].sum(axis=1)
        #  data_nssl.set_index('datetime', inplace=True, drop=False)

        #drop all the columns that we will not use past this point (to save memory/computing time)
        data_nssl = data_nssl.drop(columns=['rh', 'p', 'time', 'alt', 'Theta', 'tfast', 'tslow'])
        #  print(data_nssl.memory_usage())
        return data_nssl, 'NSSL'

    # * * *
    elif pname == 'UAS':
        if print_long == True: print("no code for reading UAS yet")
        if d_testing == True: return False
        return 'UAS'
Beispiel #22
0
def uaPlot(data, level, date, save_dir, ds, td_option):

    custom_layout = StationPlotLayout()
    custom_layout.add_barb('eastward_wind', 'northward_wind', units='knots')
    custom_layout.add_value('NW',
                            'air_temperature',
                            fmt='.0f',
                            units='degC',
                            color='darkred')

    # Geopotential height and smooth
    hght = ds.Geopotential_height_isobaric.metpy.sel(
        vertical=level * units.hPa,
        time=date,
        lat=slice(85, 15),
        lon=slice(360 - 200, 360 - 10))
    smooth_hght = mpcalc.smooth_n_point(hght, 9, 10)

    # Temperature, smooth, and convert to Celsius
    tmpk = ds.Temperature_isobaric.metpy.sel(vertical=level * units.hPa,
                                             time=date,
                                             lat=slice(85, 15),
                                             lon=slice(360 - 200, 360 - 10))
    smooth_tmpc = (mpcalc.smooth_n_point(tmpk, 9, 10)).to('degC')

    #Calculate Theta-e
    rh = ds.Relative_humidity_isobaric.metpy.sel(vertical=level * units.hPa,
                                                 time=date,
                                                 lat=slice(85, 15),
                                                 lon=slice(
                                                     360 - 200, 360 - 10))
    td = mpcalc.dewpoint_from_relative_humidity(tmpk, rh)
    te = mpcalc.equivalent_potential_temperature(level * units.hPa, tmpk, td)
    smooth_te = mpcalc.smooth_n_point(te, 9, 10)

    #decide on the height format based on the level
    if level == 250:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        cint = 120
        tint = 5
    if level == 300:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        cint = 120
        tint = 5
    if level == 500:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[0:3],
                                units='m',
                                color='black')
        cint = 60
        tint = 5
    if level == 700:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        custom_layout.add_value('SW', 'tdd', units='degC', color='green')
        custom_layout.add_value('SE', 'thetae', units='degK', color='orange')
        temps = 'Tdd, and Theta-e'
        cint = 30
        tint = 4
    if level == 850:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        if td_option == True:
            custom_layout.add_value('SW',
                                    'dew_point_temperature',
                                    units='degC',
                                    color='green')
            temps = 'Td, and Theta-e'
        if td_option == False:
            custom_layout.add_value('SW', 'tdd', units='degC', color='green')
            temps = 'Tdd, and Theta-e'
        # custom_layout.add_value('SW', 'tdd', units='degC', color='green')
        # temps = 'Tdd, and Theta-e'
        custom_layout.add_value('SE', 'thetae', units='degK', color='orange')
        cint = 30
        tint = 4
    if level == 925:
        custom_layout.add_value('NE',
                                'height',
                                fmt=lambda v: format(v, '1')[1:4],
                                units='m',
                                color='black')
        if td_option == True:
            custom_layout.add_value('SW',
                                    'dew_point_temperature',
                                    units='degC',
                                    color='green')
            temps = 'Td, and Theta-e'
        if td_option == False:
            custom_layout.add_value('SW', 'tdd', units='degC', color='green')
            temps = 'Tdd, and Theta-e'
        custom_layout.add_value('SE', 'thetae', units='degK', color='orange')
        cint = 30
        tint = 4

    globe = ccrs.Globe(ellipse='sphere',
                       semimajor_axis=6371200.,
                       semiminor_axis=6371200.)
    proj = ccrs.Stereographic(central_longitude=-105.,
                              central_latitude=90.,
                              globe=globe,
                              true_scale_latitude=60)
    # Plot the image
    fig = plt.figure(figsize=(40, 40))
    ax = fig.add_subplot(1, 1, 1, projection=proj)
    state_boundaries = feat.NaturalEarthFeature(
        category='cultural',
        name='admin_1_states_provinces_lines',
        scale='10m',
        facecolor='none')
    coastlines = feat.NaturalEarthFeature('physical',
                                          'coastline',
                                          '50m',
                                          facecolor='none')
    lakes = feat.NaturalEarthFeature('physical',
                                     'lakes',
                                     '50m',
                                     facecolor='none')
    countries = feat.NaturalEarthFeature('cultural',
                                         'admin_0_countries',
                                         '50m',
                                         facecolor='none')
    ax.add_feature(state_boundaries, zorder=2, edgecolor='grey')
    ax.add_feature(lakes, zorder=2, edgecolor='grey')
    ax.add_feature(coastlines, zorder=2, edgecolor='grey')
    ax.add_feature(lakes, zorder=2, edgecolor='grey')
    ax.add_feature(countries, zorder=2, edgecolor='grey')
    ax.coastlines(resolution='50m', zorder=2, color='grey')
    ax.set_extent([-132., -70, 26., 80.], ccrs.PlateCarree())

    stationData = dataDict(data)
    stationplot = StationPlot(ax,
                              stationData['longitude'],
                              stationData['latitude'],
                              transform=ccrs.PlateCarree(),
                              fontsize=22)
    custom_layout.plot(stationplot, stationData)

    # Plot Solid Contours of Geopotential Height
    cs = ax.contour(hght.lon,
                    hght.lat,
                    smooth_hght.m,
                    range(0, 20000, cint),
                    colors='black',
                    transform=ccrs.PlateCarree())
    clabels = plt.clabel(cs,
                         fmt='%d',
                         colors='white',
                         inline_spacing=5,
                         use_clabeltext=True,
                         fontsize=22)

    # Contour labels with black boxes and white text
    for t in clabels:
        t.set_bbox({'facecolor': 'black', 'pad': 4})
        t.set_fontweight('heavy')

    #Check levels for different contours
    if level == 250 or level == 300 or level == 500:
        # Plot Dashed Contours of Temperature
        cs2 = ax.contour(hght.lon,
                         hght.lat,
                         smooth_tmpc.m,
                         range(-60, 51, tint),
                         colors='red',
                         transform=ccrs.PlateCarree())
        clabels = plt.clabel(cs2,
                             fmt='%d',
                             colors='red',
                             inline_spacing=5,
                             use_clabeltext=True,
                             fontsize=22)
        # Set longer dashes than default
        for c in cs2.collections:
            c.set_dashes([(0, (5.0, 3.0))])
        temps = 'T'
    if level == 700 or level == 850 or level == 925:
        # Plot Dashed Contours of Temperature
        cs2 = ax.contour(hght.lon,
                         hght.lat,
                         smooth_te.m,
                         range(210, 360, tint),
                         colors='orange',
                         transform=ccrs.PlateCarree())
        clabels = plt.clabel(cs2,
                             fmt='%d',
                             colors='orange',
                             inline_spacing=5,
                             use_clabeltext=True,
                             fontsize=22)
        # Set longer dashes than default
        for c in cs2.collections:
            c.set_dashes([(0, (5.0, 3.0))])

    dpi = plt.rcParams['savefig.dpi'] = 255
    date = date + timedelta(hours=6)
    text = AnchoredText(str(level) + 'mb Wind, Heights, and ' + temps +
                        ' Valid: {0:%Y-%m-%d} {0:%H}:00UTC'.format(date),
                        loc=3,
                        frameon=True,
                        prop=dict(fontsize=22))
    ax.add_artist(text)
    plt.tight_layout()
    save_fname = '{0:%Y%m%d_%H}z_'.format(date) + str(level) + 'mb.pdf'
    plt.savefig(save_dir / save_fname, dpi=dpi, bbox_inches='tight')
Beispiel #23
0
def scalardata(field, valid_time, targetdir=".", debug=False):
    # Get color map, levels, and netCDF variable name appropriate for requested variable (from fieldinfo module).
    info = fieldinfo[field]
    if debug:
        print("scalardata: found", field, "fieldinfo:", info)
    cmap = colors.ListedColormap(info['cmap'])
    levels = info['levels']
    fvar = info['fname'][0]

    # Get narr file and filename.
    ifile = get(valid_time, targetdir=targetdir, narrtype=info['filename'])

    if debug:
        print("About to open " + ifile)
    nc = xarray.open_dataset(ifile)
    # Tried to rename vars and dimensions so metpy.parse_cf() would not warn "Found latitude/longitude values, assuming latitude_longitude for projection grid_mapping variable"
    # It didn't help. Only commenting out the metpy.parse_cf() line helped.
    # It didn't help with MetpyDeprecationWarning: Multidimensional coordinate lat assigned for axis "y". This behavior has been deprecated and will be removed in v1.0 (only one-dimensional coordinates will be available for the "y" axis) either
    #nc = nc.rename_vars({"gridlat_221": "lat", "gridlon_221" : "lon"})
    #nc = nc.rename_dims({"gridx_221": "x", "gridy_221" : "y"})
    #nc = nc.metpy.parse_cf() # TODO: figure out why filled contour didn't have .metpy.parse_cf()

    if fvar not in nc.variables:
        print(fvar, "not in", ifile, '. Try', nc.var())
        sys.exit(1)

    # Define data array. Speed and shear derived differently.
    # Define 'long_name' attribute
    #
    if field[0:5] == "speed":
        u = nc[info['fname'][0]]
        v = nc[info['fname'][1]]
        data = u  # copy metadata/coordinates from u
        data.values = wind_speed(u, v)
        data.attrs['long_name'] = "wind speed"
    elif field[0:3] == 'shr' and '_' in field:
        du, dv = shear(field,
                       valid_time=valid_time,
                       targetdir=targetdir,
                       debug=debug)
        ws = wind_speed(du, dv)
        attrs = {
            'long_name': 'wind shear',
            'units': str(ws.units),
            'verttitle': du.attrs["verttitle"]
        }
        # Use .m magnitude because you can't transfer units of pint quantity to xarray numpy array (xarray.values)
        data = xarray.DataArray(data=ws.m,
                                dims=du.dims,
                                coords=du.coords,
                                name=field,
                                attrs=attrs)
    elif field == 'theta2':
        pres = nc[info['fname'][0]]
        temp = nc[info['fname'][1]]
        data = pres  # retain xarray metadata/coordinates
        theta = potential_temperature(pres, temp)
        data.values = theta
        data.attrs['units'] = str(theta.units)
        data.attrs['long_name'] = 'potential temperature'
    elif field == 'thetae2':
        pres = nc[info['fname'][0]]
        temp = nc[info['fname'][1]]
        dwpt = nc[info['fname'][2]]
        data = pres  # retain xarray metadata/coordinates
        thetae = equivalent_potential_temperature(pres, temp, dwpt)
        data.values = thetae
        data.attrs['units'] = str(thetae.units)
        data.attrs['long_name'] = 'equivalent potential temperature'
    elif field == 'scp' or field == 'stp' or field == 'tctp':
        cape = nc[info['fname'][0]]
        cin = nc[info['fname'][1]]
        ifile = get(valid_time, targetdir=targetdir, narrtype=narrFlx)
        ncFlx = xarray.open_dataset(ifile).metpy.parse_cf()
        srh = ncFlx[info['fname'][2]]
        shear_layer = info['fname'][3]
        bulk_shear = scalardata(shear_layer,
                                valid_time,
                                targetdir=targetdir,
                                debug=debug)
        lifted_condensation_level_height = scalardata('zlcl',
                                                      valid_time,
                                                      targetdir=targetdir,
                                                      debug=debug)

        if field == 'scp':
            # In SPC help, cin is positive in SCP formulation.
            cin_term = -40 / cin
            cin_term = cin_term.where(cin < -40, other=1)
            scp = supercell_composite(cape, srh,
                                      bulk_shear) * cin_term.metpy.unit_array
            attrs = {
                'units': str(scp.units),
                'long_name': 'supercell composite parameter'
            }
            data = xarray.DataArray(data=scp,
                                    dims=cape.dims,
                                    coords=cape.coords,
                                    name=field,
                                    attrs=attrs)
        if field == 'stp':
            cin_term = (200 + cin) / 150
            cin_term = cin_term.where(cin <= -50, other=1)
            cin_term = cin_term.where(cin >= -200, other=0)
            # CAPE, srh, bulk_shear, cin may be one vertical level, but LCL may be multiple heights.
            # xarray.broadcast() makes them all multiple heights with same shape, so significant_tornado doesn't
            # complain about expecting lat/lon 2 dimensions and getting 3 dimensions..
            (cape, lifted_condensation_level_height, srh, bulk_shear,
             cin_term) = xarray.broadcast(cape,
                                          lifted_condensation_level_height,
                                          srh, bulk_shear, cin_term)
            stp = significant_tornado(cape, lifted_condensation_level_height,
                                      srh,
                                      bulk_shear) * cin_term.metpy.unit_array
            attrs = {
                'units': str(stp.units),
                'long_name': 'significant tornado parameter',
                'verttitle':
                lifted_condensation_level_height.attrs['verttitle']
            }
            data = xarray.DataArray(data=stp,
                                    dims=cape.dims,
                                    coords=cape.coords,
                                    name=field,
                                    attrs=attrs)
        if field == 'tctp':
            tctp = srh / (40 * munits['m**2/s**2']) * bulk_shear / (
                12 * munits['m/s']) * (2000 - lifted_condensation_level_height
                                       ) / (1400 * munits.m)
            # But NARR storm relative helicity (srh) is 0-3 km AGL, while original TCTP expects 0-1 km AGL.
            # So the shear term is too large using the NARR srh. Normalize the srh term with a larger denominator.
            # In STP, srh is normalized by 150 m**2/s**2. Use that.
            tctp_0_3kmsrh = srh / (150 * munits['m**2/s**2']) * bulk_shear / (
                12 * munits['m/s']) * (2000 - lifted_condensation_level_height
                                       ) / (1400 * munits.m)
            attrs = {
                'units': 'dimensionless',
                'long_name': 'TC tornado parameter'
            }
            data = xarray.DataArray(data=tctp_0_3kmsrh,
                                    dims=cape.dims,
                                    coords=cape.coords,
                                    name=field,
                                    attrs=attrs)
    elif field == 'lcl':
        pres = nc[info['fname'][0]]
        temp = nc[info['fname'][1]]
        dwpt = nc[info['fname'][2]]
        LCL_pressure, LCL_temperature = lcl(pres.fillna(pres.mean()),
                                            temp.fillna(temp.mean()),
                                            dwpt.fillna(dwpt.mean()))
        # convert units to string or xarray.DataArray.metpy.unit_array dies with ttributeError: 'NoneType' object has no attribute 'evaluate'
        attrs = {
            "long_name": "lifted condensation level",
            "units": str(LCL_pressure.units),
            "from": "metpy.calc.lcl"
        }
        data = xarray.DataArray(data=LCL_pressure,
                                coords=pres.coords,
                                dims=pres.dims,
                                name='LCL',
                                attrs=attrs)
    elif field == 'zlcl':
        LCL_pressure = scalardata('lcl',
                                  valid_time,
                                  targetdir=targetdir,
                                  debug=debug)
        ifile = get(valid_time, targetdir=targetdir, narrtype=narr3D)
        nc3D = xarray.open_dataset(ifile).metpy.parse_cf()
        hgt3D = nc3D["HGT_221_ISBL"]
        data = pressure_to_height(LCL_pressure, hgt3D, targetdir=targetdir)
    else:
        data = nc[fvar]
    data = units(data, info, debug=debug)
    data = vertical(data, info, debug=debug)
    data = temporal(data, info, debug=debug)

    data.attrs['field'] = field
    data.attrs['ifile'] = os.path.realpath(ifile)
    data.attrs['levels'] = levels
    data.attrs['cmap'] = cmap

    if data.min() > levels[-1] or data.max() < levels[0]:
        print('levels', levels, 'out of range of data', data.min(), data.max())
        sys.exit(2)

    return data
def Time_Crossection_rh_uv_theta_e(
        initTime=None,
        model='ECMWF',
        points={
            'lon': [116.3833],
            'lat': [39.9]
        },
        levels=[1000, 950, 925, 900, 850, 800, 700, 600, 500, 400, 300, 200],
        t_gap=3,
        t_range=[0, 48],
        output_dir=None):

    fhours = np.arange(t_range[0], t_range[1], t_gap)

    # 读数据

    try:
        data_dir = [
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='TMP',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='UGRD',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='VGRD',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='RH',
                              lvl='')
        ]
    except KeyError:
        raise ValueError('Can not find all directories needed')

    if (initTime == None):
        initTime = get_latest_initTime(data_dir[0][0:-1] + "850")
    filenames = [initTime + '.' + str(fhour).zfill(3) for fhour in fhours]
    TMP_4D = get_model_3D_grids(directory=data_dir[0][0:-1],
                                filenames=filenames,
                                levels=levels,
                                allExists=False)
    TMP_2D = TMP_4D.interp(lon=('points', points['lon']),
                           lat=('points', points['lat']))

    filenames = [initTime + '.' + str(fhour).zfill(3) for fhour in fhours]
    u_4D = get_model_3D_grids(directory=data_dir[1][0:-1],
                              filenames=filenames,
                              levels=levels,
                              allExists=False)
    u_2D = u_4D.interp(lon=('points', points['lon']),
                       lat=('points', points['lat']))

    filenames = [initTime + '.' + str(fhour).zfill(3) for fhour in fhours]
    v_4D = get_model_3D_grids(directory=data_dir[2][0:-1],
                              filenames=filenames,
                              levels=levels,
                              allExists=False)
    v_2D = v_4D.interp(lon=('points', points['lon']),
                       lat=('points', points['lat']))

    filenames = [initTime + '.' + str(fhour).zfill(3) for fhour in fhours]
    rh_4D = get_model_3D_grids(directory=data_dir[3][0:-1],
                               filenames=filenames,
                               levels=levels,
                               allExists=False)
    rh_2D = rh_4D.interp(lon=('points', points['lon']),
                         lat=('points', points['lat']))
    rh_2D.attrs['model'] = model
    rh_2D.attrs['points'] = points
    Td_2D = mpcalc.dewpoint_rh(TMP_2D['data'].values * units.celsius,
                               rh_2D['data'].values * units.percent)

    rh, pressure = xr.broadcast(rh_2D['data'], rh_2D['level'])

    Theta_e = mpcalc.equivalent_potential_temperature(
        pressure, TMP_2D['data'].values * units.celsius, Td_2D)

    theta_e_2D = xr.DataArray(np.array(Theta_e),
                              coords=rh_2D['data'].coords,
                              dims=rh_2D['data'].dims,
                              attrs={'units': Theta_e.units})

    crossection_graphics.draw_Time_Crossection_rh_uv_theta_e(
        rh_2D=rh_2D,
        u_2D=u_2D,
        v_2D=v_2D,
        theta_e_2D=theta_e_2D,
        t_range=t_range,
        output_dir=output_dir)
Beispiel #25
0
def test_equivalent_potential_temperature():
    """Test equivalent potential temperature calculation."""
    p = 999. * units.mbar
    t = 288. * units.kelvin
    ept = equivalent_potential_temperature(p, t)
    assert_almost_equal(ept, 315.9548 * units.kelvin, 3)
Beispiel #26
0
def Time_Crossection_rh_uv_theta_e(initTime=None,model='ECMWF',data_source='MICAPS',points={'lon':[116.3833], 'lat':[39.9]},
    levels=[1000, 950, 925, 900, 850, 800, 700,600,500,400,300,200],
    t_gap=3,t_range=[0,48],output_dir=None,**kwargs):
  
    fhours = np.arange(t_range[0], t_range[1], t_gap)

    if(data_source == 'MICAPS'):
        try:
            data_dir = [utl.Cassandra_dir(data_type='high',data_source=model,var_name='TMP',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='UGRD',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='VGRD',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='RH',lvl=''),
                        utl.Cassandra_dir(data_type='surface',data_source=model,var_name='PSFC')]
        except KeyError:
            raise ValueError('Can not find all directories needed')
        
        if(initTime==None):
            initTime = get_latest_initTime(data_dir[0][0:-1]+"850")
        filenames = [initTime+'.'+str(fhour).zfill(3) for fhour in fhours]
        TMP_4D=get_model_3D_grids(directory=data_dir[0][0:-1],filenames=filenames,levels=levels, allExists=False)
        u_4D=get_model_3D_grids(directory=data_dir[1][0:-1],filenames=filenames,levels=levels, allExists=False)
        v_4D=get_model_3D_grids(directory=data_dir[2][0:-1],filenames=filenames,levels=levels, allExists=False)
        rh_4D=get_model_3D_grids(directory=data_dir[3][0:-1],filenames=filenames,levels=levels, allExists=False)
        Psfc_3D=get_model_grids(directory=data_dir[4][0:-1],filenames=filenames,allExists=False)

    if(data_source == 'CIMISS'):
        if(initTime != None):
            filename = utl.model_filename(initTime, 0,UTC=True)
        else:
            filename=utl.filename_day_back_model(day_back=0,fhour=0,UTC=True)
        try:
            rh_4D=CMISS_IO.cimiss_model_3D_grids(init_time_str='20'+filename[0:8],valid_times=fhours,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='RHU'),
                        fcst_levels=levels, fcst_ele="RHU", units='%',pbar=True)

            u_4D=CMISS_IO.cimiss_model_3D_grids(init_time_str='20'+filename[0:8],valid_times=fhours,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='WIU'),
                        fcst_levels=levels, fcst_ele="WIU", units='m/s',pbar=True)
                
            v_4D=CMISS_IO.cimiss_model_3D_grids(init_time_str='20'+filename[0:8],valid_times=fhours,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='WIV'),
                        fcst_levels=levels, fcst_ele="WIV", units='m/s',pbar=True)

            TMP_4D=CMISS_IO.cimiss_model_3D_grids(init_time_str='20'+filename[0:8],valid_times=fhours,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='TEM'),
                        fcst_levels=levels, fcst_ele="TEM", units='K',pbar=True)
            TMP_4D['data'].values=TMP_4D['data'].values-273.15

            Psfc_3D=CMISS_IO.cimiss_model_grids(init_time_str='20'+filename[0:8], valid_times=fhours,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='PRS'),
                        fcst_level=0, fcst_ele="PRS", units='Pa',pbar=True)

        except KeyError:
            raise ValueError('Can not find all data needed')

    TMP_2D=TMP_4D.interp(lon=('points', points['lon']), lat=('points', points['lat']))
    u_2D=u_4D.interp(lon=('points', points['lon']), lat=('points', points['lat']))
    v_2D=v_4D.interp(lon=('points', points['lon']), lat=('points', points['lat']))
    rh_2D=rh_4D.interp(lon=('points', points['lon']), lat=('points', points['lat']))
    rh_2D.attrs['model']=model
    rh_2D.attrs['points']=points
    Psfc_1D=Psfc_3D.interp(lon=('points', points['lon']), lat=('points', points['lat']))
    v_2D2,pressure_2D = xr.broadcast(v_2D['data'],v_2D['level'])
    v_2D2,Psfc_2D = xr.broadcast(v_2D['data'],Psfc_1D['data'])
    Td_2D = mpcalc.dewpoint_rh(TMP_2D['data'].values*units.celsius,
                rh_2D['data'].values* units.percent)

    terrain_2D=pressure_2D-Psfc_2D
    rh,pressure = xr.broadcast(rh_2D['data'],rh_2D['level'])
    Theta_e=mpcalc.equivalent_potential_temperature(pressure,
                                                TMP_2D['data'].values*units.celsius, 
                                                Td_2D)

    theta_e_2D = xr.DataArray(np.array(Theta_e),
                        coords=rh_2D['data'].coords,
                        dims=rh_2D['data'].dims,
                        attrs={'units': Theta_e.units})

    crossection_graphics.draw_Time_Crossection_rh_uv_theta_e(
                    rh_2D=rh_2D, u_2D=u_2D, v_2D=v_2D,theta_e_2D=theta_e_2D,terrain_2D=terrain_2D,
                    t_range=t_range,output_dir=output_dir)
Beispiel #27
0
def Crosssection_Wind_Theta_e_Qv(
    initTime=None, fhour=24,
    levels=[1000, 950, 925, 900, 850, 800, 700,600,500,400,300,200],
    day_back=0,model='GRAPES_GFS',data_source='MICAPS',
    lw_ratio=[16,9],
    output_dir=None,
    st_point = [20, 120.0],
    ed_point = [50, 130.0],
    map_extent=[70,140,15,55],
    h_pos=[0.125, 0.665, 0.25, 0.2],**kwargs ):

    if(data_source == 'MICAPS'):
        try:
            data_dir = [utl.Cassandra_dir(data_type='high',data_source=model,var_name='RH',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='UGRD',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='VGRD',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='TMP',lvl=''),
                        utl.Cassandra_dir(data_type='high',data_source=model,var_name='HGT',lvl='500'),
                        utl.Cassandra_dir(data_type='surface',data_source=model,var_name='PSFC')]
        except KeyError:
            raise ValueError('Can not find all directories needed')

        # get filename
        if(initTime != None):
            filename = utl.model_filename(initTime, fhour)
        else:
            filename=utl.filename_day_back_model(day_back=day_back,fhour=fhour)
            
        # retrieve data from micaps server
        rh=get_model_3D_grid(directory=data_dir[0][0:-1],filename=filename,levels=levels, allExists=False)
        u=get_model_3D_grid(directory=data_dir[1][0:-1],filename=filename,levels=levels, allExists=False)
        v=get_model_3D_grid(directory=data_dir[2][0:-1],filename=filename,levels=levels, allExists=False)
        v2=get_model_3D_grid(directory=data_dir[2][0:-1],filename=filename,levels=levels, allExists=False)
        t=get_model_3D_grid(directory=data_dir[3][0:-1],filename=filename,levels=levels, allExists=False)
        gh=get_model_grid(data_dir[4], filename=filename)
        psfc=get_model_grid(data_dir[5], filename=filename)
    if(data_source == 'CIMISS'):
        # get filename
        if(initTime != None):
            filename = utl.model_filename(initTime, fhour,UTC=True)
        else:
            filename=utl.filename_day_back_model(day_back=day_back,fhour=fhour,UTC=True)
        try:
            rh=CMISS_IO.cimiss_model_3D_grid(init_time_str='20'+filename[0:8],valid_time=fhour,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='RHU'),
                        fcst_levels=levels, fcst_ele="RHU", units='%')

            u=CMISS_IO.cimiss_model_3D_grid(init_time_str='20'+filename[0:8],valid_time=fhour,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='WIU'),
                        fcst_levels=levels, fcst_ele="WIU", units='m/s')
                
            v=CMISS_IO.cimiss_model_3D_grid(init_time_str='20'+filename[0:8],valid_time=fhour,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='WIV'),
                        fcst_levels=levels, fcst_ele="WIV", units='m/s')

            v2=CMISS_IO.cimiss_model_3D_grid(init_time_str='20'+filename[0:8],valid_time=fhour,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='WIV'),
                        fcst_levels=levels, fcst_ele="WIV", units='m/s')

            t=CMISS_IO.cimiss_model_3D_grid(init_time_str='20'+filename[0:8],valid_time=fhour,
                        data_code=utl.CMISS_data_code(data_source=model,var_name='TEM'),
                        fcst_levels=levels, fcst_ele="TEM", units='K')
            t['data'].values=t['data'].values-273.15

            gh=CMISS_IO.cimiss_model_by_time('20'+filename[0:8],valid_time=fhour,
                            data_code=utl.CMISS_data_code(data_source=model,var_name='GPH'),
                            fcst_level=500, fcst_ele="GPH", units='gpm')
            gh['data'].values=gh['data'].values/10.

            psfc=CMISS_IO.cimiss_model_by_time('20'+filename[0:8], valid_time=fhour,
                data_code=utl.CMISS_data_code(data_source=model,var_name='PRS'),
                fcst_level=0, fcst_ele="PRS", units='Pa')
            psfc['data']=psfc['data']/100.

        except KeyError:
            raise ValueError('Can not find all data needed')   
    rh = rh.metpy.parse_cf().squeeze()
    u = u.metpy.parse_cf().squeeze()
    v = v.metpy.parse_cf().squeeze()
    v2 = v2.metpy.parse_cf().squeeze()
    psfc=psfc.metpy.parse_cf().squeeze()
    t = t.metpy.parse_cf().squeeze()

    resolution=u['lon'][1]-u['lon'][0]
    x,y=np.meshgrid(u['lon'], u['lat'])
    # +form 3D psfc
    mask1 = (
            (psfc['lon']>=t['lon'].values.min())&
            (psfc['lon']<=t['lon'].values.max())&
            (psfc['lat']>=t['lat'].values.min())&
            (psfc['lat']<=t['lat'].values.max())
            )

    t2,psfc_bdcst=xr.broadcast(t['data'],psfc['data'].where(mask1, drop=True))
    mask2=(psfc_bdcst > -10000)
    psfc_bdcst=psfc_bdcst.where(mask2, drop=True)
    # -form 3D psfc

    dx,dy=mpcalc.lat_lon_grid_deltas(u['lon'],u['lat'])

    #rh=rh.rename(dict(lat='latitude',lon='longitude'))
    cross = cross_section(rh, st_point, ed_point)
    cross_rh=cross.set_coords(('lat', 'lon'))
    cross = cross_section(u, st_point, ed_point)
    cross_u=cross.set_coords(('lat', 'lon'))
    cross = cross_section(v, st_point, ed_point)
    cross_v=cross.set_coords(('lat', 'lon'))
    cross_psfc = cross_section(psfc_bdcst, st_point, ed_point)

    cross_u['data'].attrs['units']=units.meter/units.second
    cross_v['data'].attrs['units']=units.meter/units.second
    cross_u['t_wind'], cross_v['n_wind'] = mpcalc.cross_section_components(cross_u['data'],cross_v['data'])
    
    cross = cross_section(t, st_point, ed_point)
    cross_t=cross.set_coords(('lat', 'lon'))

    cross_Td = mpcalc.dewpoint_rh(cross_t['data'].values*units.celsius,
                cross_rh['data'].values* units.percent)

    rh,pressure = xr.broadcast(cross_rh['data'],cross_t['level'])
    pressure.attrs['units']='hPa'
    
    Qv = mpcalc.specific_humidity_from_dewpoint(cross_Td,
                pressure)

    cross_Qv = xr.DataArray(np.array(Qv)*1000.,
                    coords=cross_rh['data'].coords,
                    dims=cross_rh['data'].dims,
                    attrs={'units': units('g/kg')})

    Theta_e=mpcalc.equivalent_potential_temperature(pressure,
                                                cross_t['data'].values*units.celsius, 
                                                cross_Td)
    cross_terrain=pressure-cross_psfc

    cross_Theta_e = xr.DataArray(np.array(Theta_e),
                        coords=cross_rh['data'].coords,
                        dims=cross_rh['data'].dims,
                        attrs={'units': Theta_e.units})

    crossection_graphics.draw_Crosssection_Wind_Theta_e_Qv(
                    cross_Qv=cross_Qv, cross_Theta_e=cross_Theta_e, cross_u=cross_u,
                    cross_v=cross_v,cross_terrain=cross_terrain,gh=gh,
                    h_pos=h_pos,st_point=st_point,ed_point=ed_point,
                    levels=levels,map_extent=map_extent,lw_ratio=lw_ratio,
                    output_dir=output_dir)
def Crosssection_Wind_Theta_e_Qv(
        initial_time=None,
        fhour=24,
        levels=[1000, 950, 925, 900, 850, 800, 700, 600, 500, 400, 300, 200],
        day_back=0,
        model='ECMWF',
        output_dir=None,
        st_point=[20, 120.0],
        ed_point=[50, 130.0],
        map_extent=[70, 140, 15, 55],
        h_pos=[0.125, 0.665, 0.25, 0.2]):

    # micaps data directory
    try:
        data_dir = [
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='RH',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='UGRD',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='VGRD',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='TMP',
                              lvl=''),
            utl.Cassandra_dir(data_type='high',
                              data_source=model,
                              var_name='HGT',
                              lvl='500')
        ]
    except KeyError:
        raise ValueError('Can not find all directories needed')

    # get filename
    if (initial_time != None):
        filename = utl.model_filename(initial_time, fhour)
    else:
        filename = utl.filename_day_back_model(day_back=day_back, fhour=fhour)

    # retrieve data from micaps server
    rh = get_model_3D_grid(directory=data_dir[0][0:-1],
                           filename=filename,
                           levels=levels,
                           allExists=False)
    if rh is None:
        return
    rh = rh.metpy.parse_cf().squeeze()

    u = get_model_3D_grid(directory=data_dir[1][0:-1],
                          filename=filename,
                          levels=levels,
                          allExists=False)
    if u is None:
        return
    u = u.metpy.parse_cf().squeeze()

    v = get_model_3D_grid(directory=data_dir[2][0:-1],
                          filename=filename,
                          levels=levels,
                          allExists=False)
    if v is None:
        return
    v = v.metpy.parse_cf().squeeze()

    v2 = get_model_3D_grid(directory=data_dir[2][0:-1],
                           filename=filename,
                           levels=levels,
                           allExists=False)
    if v2 is None:
        return
    v2 = v2.metpy.parse_cf().squeeze()

    t = get_model_3D_grid(directory=data_dir[3][0:-1],
                          filename=filename,
                          levels=levels,
                          allExists=False)
    if t is None:
        return
    t = t.metpy.parse_cf().squeeze()

    gh = get_model_grid(data_dir[4], filename=filename)
    if t is None:
        return

    resolution = u['lon'][1] - u['lon'][0]
    x, y = np.meshgrid(u['lon'], u['lat'])

    dx, dy = mpcalc.lat_lon_grid_deltas(u['lon'], u['lat'])
    for ilvl in levels:
        u2d = u.sel(level=ilvl)
        #u2d['data'].attrs['units']=units.meter/units.second
        v2d = v.sel(level=ilvl)
        #v2d['data'].attrs['units']=units.meter/units.second

        absv2d = mpcalc.absolute_vorticity(
            u2d['data'].values * units.meter / units.second,
            v2d['data'].values * units.meter / units.second, dx, dy,
            y * units.degree)

        if (ilvl == levels[0]):
            absv3d = v2
            absv3d['data'].loc[dict(level=ilvl)] = np.array(absv2d)
        else:
            absv3d['data'].loc[dict(level=ilvl)] = np.array(absv2d)
    absv3d['data'].attrs['units'] = absv2d.units

    #rh=rh.rename(dict(lat='latitude',lon='longitude'))
    cross = cross_section(rh, st_point, ed_point)
    cross_rh = cross.set_coords(('lat', 'lon'))
    cross = cross_section(u, st_point, ed_point)
    cross_u = cross.set_coords(('lat', 'lon'))
    cross = cross_section(v, st_point, ed_point)
    cross_v = cross.set_coords(('lat', 'lon'))

    cross_u['data'].attrs['units'] = units.meter / units.second
    cross_v['data'].attrs['units'] = units.meter / units.second
    cross_u['t_wind'], cross_v['n_wind'] = mpcalc.cross_section_components(
        cross_u['data'], cross_v['data'])

    cross = cross_section(t, st_point, ed_point)
    cross_t = cross.set_coords(('lat', 'lon'))
    cross = cross_section(absv3d, st_point, ed_point)

    cross_Td = mpcalc.dewpoint_rh(cross_t['data'].values * units.celsius,
                                  cross_rh['data'].values * units.percent)

    rh, pressure = xr.broadcast(cross_rh['data'], cross_t['level'])

    Qv = mpcalc.specific_humidity_from_dewpoint(cross_Td, pressure)

    cross_Qv = xr.DataArray(np.array(Qv) * 1000.,
                            coords=cross_rh['data'].coords,
                            dims=cross_rh['data'].dims,
                            attrs={'units': units('g/kg')})

    Theta_e = mpcalc.equivalent_potential_temperature(
        pressure, cross_t['data'].values * units.celsius, cross_Td)

    cross_Theta_e = xr.DataArray(np.array(Theta_e),
                                 coords=cross_rh['data'].coords,
                                 dims=cross_rh['data'].dims,
                                 attrs={'units': Theta_e.units})

    crossection_graphics.draw_Crosssection_Wind_Theta_e_Qv(
        cross_Qv=cross_Qv,
        cross_Theta_e=cross_Theta_e,
        cross_u=cross_u,
        cross_v=cross_v,
        gh=gh,
        h_pos=h_pos,
        st_point=st_point,
        ed_point=ed_point,
        levels=levels,
        map_extent=map_extent,
        output_dir=output_dir)
def metpy_temp_adv(fname, plevels, tidx):

    ds = xr.open_dataset(fname).metpy.parse_cf().squeeze()
    ds = ds.isel(Time=tidx)
    print(ds)

    dx, dy = mpcalc.lat_lon_grid_deltas(ds.lon.values * units('degrees_E'),
                                        ds.lat.values * units('degrees_N'))

    plevels_unit = plevels * units.hPa

    ds1 = xr.Dataset()

    p = units.Quantity(to_np(ds.p), 'hPa')
    z = units.Quantity(to_np(ds.z), 'meter')
    u = units.Quantity(to_np(ds.u), 'm/s')
    v = units.Quantity(to_np(ds.v), 'm/s')
    w = units.Quantity(to_np(ds.w), 'm/s')
    tk = units.Quantity(to_np(ds.tk), 'kelvin')
    th = units.Quantity(to_np(ds.th), 'kelvin')
    eth = units.Quantity(to_np(ds.eth), 'kelvin')
    wspd = units.Quantity(to_np(ds.wspd), 'm/s')
    omega = units.Quantity(to_np(ds.omega), 'Pa/s')
    z, u, v, w, tk, th, eth, wspd, omega = log_interpolate_1d(plevels_unit,
                                                              p,
                                                              z,
                                                              u,
                                                              v,
                                                              w,
                                                              tk,
                                                              th,
                                                              eth,
                                                              wspd,
                                                              omega,
                                                              axis=0)

    coords, dims = [plevs, ds.lat.values,
                    ds.lon.values], ["level", "lat", "lon"]
    for name, var in zip(
        ['z', 'u', 'v', 'w', 'tk', 'th', 'eth', 'wspd', 'omega'],
        [z, u, v, w, tk, th, eth, wspd, omega]):
        #g = ndimage.gaussian_filter(var, sigma=3, order=0)
        ds1[name] = xr.DataArray(to_np(var), coords=coords, dims=dims)

    # Calculate temperature advection using metpy function
    for i, plev in enumerate(plevs):

        uqvect, vqvect = mpcalc.q_vector(u[i, :, :], v[i, :, :], th[i, :, :],
                                         plev * units.hPa, dx, dy)
        #uqvect, vqvect = mpcalc.q_vector(u[i,:,:], v[i,:,:], th.to('degC')[i,:,:], plev*units.hPa, dx, dy)
        q_div = -2 * mpcalc.divergence(uqvect, vqvect, dx, dy, dim_order='yx')
        ds1['uq_{:03d}'.format(plev)] = xr.DataArray(
            np.array(uqvect),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])
        ds1['vq_{:03d}'.format(plev)] = xr.DataArray(
            np.array(vqvect),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])
        ds1['q_div_{:03d}'.format(plev)] = xr.DataArray(
            np.array(q_div),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

        #        adv = mpcalc.advection(tk[i,:,:], [u[i,:,:], v[i,:,:]], (dx, dy), dim_order='yx') * units('K/sec')
        #        adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec')
        #        ds1['tk_adv_{:03d}'.format(plev)] = xr.DataArray(np.array(adv), coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"])
        #
        #        adv = mpcalc.advection(th[i,:,:], [u[i,:,:], v[i,:,:]], (dx, dy), dim_order='yx') * units('K/sec')
        #        adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec')
        #        ds1['th_adv_{:03d}'.format(plev)] = xr.DataArray(np.array(adv), coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"])
        #
        adv = mpcalc.advection(eth[i, :, :], [u[i, :, :], v[i, :, :]],
                               (dx, dy),
                               dim_order='yx') * units('K/sec')
        adv = ndimage.gaussian_filter(adv, sigma=3, order=0) * units('K/sec')
        ds1['eth_adv_{:03d}'.format(plev)] = xr.DataArray(
            np.array(adv),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

        div = mpcalc.divergence(u[i, :, :], v[i, :, :], dx, dy, dim_order='yx')
        div = ndimage.gaussian_filter(div, sigma=3, order=0) * units('1/sec')
        ds1['div_{:03d}'.format(plev)] = xr.DataArray(
            np.array(div),
            coords=[ds.lat.values, ds.lon.values],
            dims=["lat", "lon"])

    ds1['Time'] = ds.Time
    eth2 = mpcalc.equivalent_potential_temperature(
        ds.slp.values * units.hPa, ds.t2m.values * units('K'),
        ds.td2.values * units('celsius'))
    ds1['eth2'] = xr.DataArray(eth2,
                               coords=[ds.lat.values, ds.lon.values],
                               dims=["lat", "lon"])
    ds1['sst'] = xr.DataArray(
        ndimage.gaussian_filter(ds.sst.values, sigma=3, order=0) - 273.15,
        coords=[ds.lat.values, ds.lon.values],
        dims=["lat", "lon"])
    ds1['t2m'] = xr.DataArray(ds.t2m.values,
                              coords=[ds.lat.values, ds.lon.values],
                              dims=["lat", "lon"])
    ds1['th2'] = xr.DataArray(ds.th2.values,
                              coords=[ds.lat.values, ds.lon.values],
                              dims=["lat", "lon"])
    ds1['mask'] = xr.DataArray(ds.mask.values,
                               coords=[ds.lat.values, ds.lon.values],
                               dims=["lat", "lon"])

    ds1['u10'] = xr.DataArray(ds.u10.values,
                              coords=[ds.lat.values, ds.lon.values],
                              dims=["lat", "lon"])
    ds1['v10'] = xr.DataArray(ds.v10.values,
                              coords=[ds.lat.values, ds.lon.values],
                              dims=["lat", "lon"])
    ds1['slp'] = xr.DataArray(ds.slp.values,
                              coords=[ds.lat.values, ds.lon.values],
                              dims=["lat", "lon"])
    ds1['rain'] = xr.DataArray(ds.rain.values,
                               coords=[ds.lat.values, ds.lon.values],
                               dims=["lat", "lon"])
    ds1['accrain'] = xr.DataArray(ds.accrain.values,
                                  coords=[ds.lat.values, ds.lon.values],
                                  dims=["lat", "lon"])
    #ds1['latent'] = xr.DataArray(ds.latent.values, coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"])
    #ds1['acclatent'] = xr.DataArray(ds.acclatent.values, coords=[ds.lat.values,ds.lon.values], dims=["lat","lon"])

    return ds1
Beispiel #30
0
def main():
    ### START OF USER SETTINGS BLOCK ###
    # FILE/DATA SETTINGS
    # file path to input
    datafile = '/home/jgodwin/python/sfc_observations/surface_observations.txt'
    timefile = '/home/jgodwin/python/sfc_observations/validtime.txt'

    # MAP SETTINGS
    # map names (for tracking purposes)
    maps = ['CONUS','Texas','Floater 1']
    restart_domain = [True,False]
    # map boundaries
    west = [-120,-108,-108]
    east = [-70,-93,-85]
    south = [20,25,37]
    north = [50,38,52]

    # OUTPUT SETTINGS
    # save directory for output
    savedir = '/var/www/html/images/'
    # filenames ("_[variable].png" will be appended, so only a descriptor like "conus" is needed)
    savenames = ['conus','texas','floater1']

    # TEST MODE SETTINGS
    test = False
    testnum = 3

    ### END OF USER SETTINGS BLOCK ###

    for i in range(len(maps)):
        if test and i != testnum:
            continue
        print(maps[i])
        # create the map projection
        cenlon = (west[i] + east[i]) / 2.0
        cenlat = (south[i] + north[i]) / 2.0
        sparallel = cenlat
        if cenlat > 0:
            cutoff = -30
            flip = False
        elif cenlat < 0:
            cutoff = 30
            flip = True
        if restart_domain:
            to_proj = ccrs.LambertConformal(central_longitude=cenlon,central_latitude=cenlat,standard_parallels=[sparallel],cutoff=cutoff)
        # open the data
        vt = open(timefile).read()
        with open(datafile) as f:
            data = pd.read_csv(f,header=0,names=['siteID','lat','lon','elev','slp','temp','sky','dpt','wx','wdr',\
                'wsp'],na_values=-99999)

        # filter data by lat/lon
        data = data[(data['lat'] >= south[i]-2.0) & (data['lat'] <= north[i]+2.0) & (data['lon'] >= west[i]-2.0)\
            & (data['lon'] <= east[i]+2.0)]
        # remove questionable data
        data = data[(cToF(data['temp']) <= 120) & (cToF(data['dpt']) <= 80)]

        # project lat/lon onto final projection
        print("Creating map projection.")
        lon = data['lon'].values
        lat = data['lat'].values
        xp, yp, _ = to_proj.transform_points(ccrs.Geodetic(), lon, lat).T

        # remove missing data from pressure and interpolate
        # we'll give this a try and see if it can help with my CPU credit problem
        if restart_domain:
            print("Performing Cressman interpolation.")
            x_masked, y_masked, pres = remove_nan_observations(xp, yp, data['slp'].values)
            slpgridx, slpgridy, slp = interpolate_to_grid(x_masked, y_masked, pres, interp_type='cressman',
                                                          minimum_neighbors=1, search_radius=400000,
                                                          hres=100000)

            # get wind information and remove missing data
            wind_speed = (data['wsp'].values * units('knots'))
            wind_dir = data['wdr'].values * units.degree
            good_indices = np.where((~np.isnan(wind_dir)) & (~np.isnan(wind_speed)))
            x_masked = xp[good_indices]
            y_masked = yp[good_indices]
            wind_speed = wind_speed[good_indices]
            wind_dir = wind_dir[good_indices]
            u, v = wind_components(wind_speed, wind_dir)
            windgridx, windgridy, uwind = interpolate_to_grid(x_masked, y_masked, np.array(u),
                                                              interp_type='cressman', search_radius=400000,
                                                              hres=100000)
            _, _, vwind = interpolate_to_grid(x_masked, y_masked, np.array(v), interp_type='cressman',
                                              search_radius=400000, hres=100000)

            # get temperature information
            data['temp'] = cToF(data['temp'])
            x_masked, y_masked, t = remove_nan_observations(xp, yp, data['temp'].values)
            tempx, tempy, temp = interpolate_to_grid(x_masked, y_masked, t, interp_type='cressman',
                                                     minimum_neighbors=3, search_radius=200000, hres=18000)
            temp = np.ma.masked_where(np.isnan(temp), temp)

            # get dewpoint information
            data['dpt'] = cToF(data['dpt'])
            x_masked,y_masked,td = remove_nan_observations(xp,yp,data['dpt'].values)
            dptx,dpty,dewp = interpolate_to_grid(x_masked,y_masked,td,interp_type='cressman',\
                minimum_neighbors=3,search_radius=200000,hres=18000)
            dewp = np.ma.masked_where(np.isnan(dewp),dewp)

            # interpolate wind speed
            x_masked,y_masked,wspd = remove_nan_observations(xp,yp,data['wsp'].values)
            wspx,wspy,speed = interpolate_to_grid(x_masked,y_masked,wspd,interp_type='cressman',\
                minimum_neighbors=3,search_radius=200000,hres=18000)
            speed = np.ma.masked_where(np.isnan(speed),speed)

            # derived values
            # station pressure
            data['pres'] = stationPressure(data['slp'],data['elev'])
            # theta-E
            data['thetae'] = equivalent_potential_temperature(data['pres'].values*units.hPa,data['temp'].values*units.degF,data['dpt'].values*units.degF)
            x_masked,y_masked,thetae = remove_nan_observations(xp,yp,data['thetae'].values)
            thex,they,thte = interpolate_to_grid(x_masked,y_masked,thetae,interp_type='cressman',\
                minimum_neighbors=3,search_radius=200000,hres=18000)
            thte = np.ma.masked_where(np.isnan(thte),thte)

            # mixing ratio
            relh = relative_humidity_from_dewpoint(data['temp'].values*units.degF,data['dpt'].values*units.degF)
            mixr = mixing_ratio_from_relative_humidity(relh,data['temp'].values*units.degF,data['pres'].values*units.hPa) * 1000.0
            x_masked,y_masked,mixrat = remove_nan_observations(xp,yp,mixr)
            mrx,mry,mrat = interpolate_to_grid(x_masked,y_masked,mixrat,interp_type='cressman',\
                minimum_neighbors=3,search_radius=200000,hres=18000)
            mrat = np.ma.masked_where(np.isnan(mrat),mrat)

        # set up the state borders
        state_boundaries = cfeature.NaturalEarthFeature(category='cultural',\
            name='admin_1_states_provinces_lines',scale='50m',facecolor='none')

        # SCALAR VARIABLES TO PLOT
        # variable names (will appear in plot title)
        variables = ['Temperature','Dewpoint','Wind Speed','Theta-E','Mixing Ratio']
        # units (for colorbar label)
        unitlabels = ['F','F','kt','K','g/kg']
        # list of actual variables to plot
        vardata = [temp,dewp,speed,thte,mrat]
        # tag in output filename
        varplots = ['temp','dewp','wspd','thte','mrat']
        # levels: (lower,upper,step)
        levs = [[-20,105,5],[30,85,5],[0,70,5],[250,380,5],[0,22,2]]
        # colormaps
        colormaps = ['hsv_r','Greens','plasma','hsv_r','Greens']

        for j in range(len(variables)):
            print("\t%s" % variables[j])
            fig = plt.figure(figsize=(20, 10))
            view = fig.add_subplot(1, 1, 1, projection=to_proj)
            
            # set up the map and plot the interpolated grids
            levels = list(range(levs[j][0],levs[j][1],levs[j][2]))
            cmap = plt.get_cmap(colormaps[j])
            norm = BoundaryNorm(levels, ncolors=cmap.N, clip=True)
            labels = variables[j] + " (" + unitlabels[j] + ")"

            # add map features
            view.set_extent([west[i],east[i],south[i],north[i]])
            view.add_feature(state_boundaries,edgecolor='black')
            view.add_feature(cfeature.OCEAN,zorder=-1)
            view.add_feature(cfeature.COASTLINE,zorder=2)
            view.add_feature(cfeature.BORDERS, linewidth=2,edgecolor='black')

            # plot the sea-level pressure
            cs = view.contour(slpgridx, slpgridy, slp, colors='k', levels=list(range(990, 1034, 4)))
            view.clabel(cs, inline=1, fontsize=12, fmt='%i')

            # plot the scalar background
            mmb = view.pcolormesh(tempx, tempy, vardata[j], cmap=cmap, norm=norm)
            fig.colorbar(mmb, shrink=.4, orientation='horizontal', pad=0.02, boundaries=levels, \
                extend='both',label=labels)

            # plot the wind barbs
            view.barbs(windgridx, windgridy, uwind, vwind, alpha=.4, length=5,flip_barb=flip)

            # plot title and save
            view.set_title('%s (shaded), SLP, and Wind (valid %s)' % (variables[j],vt))
            plt.savefig('/var/www/html/images/%s_%s.png' % (savenames[i],varplots[j]),bbox_inches='tight')

            # close everything
            fig.clear()
            view.clear()
            plt.close(fig)
            f.close()

    print("Script finished.")
Beispiel #31
0
        # noL  = list(launch.keys())[-8:]
        noL = list(launch.keys())[-12:]
        # colorL = ['r','o','y','g','b','p','k','']
        cmap = cm.get_cmap('rainbow', 10)
        colorL = cmap(range(10))
        i = 0
        for no in noL:
            time = dtmdtm.strptime(launch[f"{no}"], "%Y/%m/%d %H:%M:%S")
            print(no, time)
            st = STreader(no, launch[f"{no}"], Path('../../data/ST'))
            try:

                P, T, Td, U, V = st.read()
                Theta = mcalc.potential_temperature(P, T).to('K')
                print(Theta)
                Thetae = mcalc.equivalent_potential_temperature(P, T,
                                                                Td).to('K')

                ## UTC
                UTC = max((time + dtmdt(minutes=25)).hour,
                          (time - dtmdt(minutes=25)).hour) - 8
                LST = max((time + dtmdt(minutes=25)).hour,
                          (time - dtmdt(minutes=25)).hour)
                if (UTC < 0):
                    UTC += 24
                    title = (time - dtmdt(days=1)).strftime('%m%d')
                else:
                    title = time.strftime('%m%d')

                ## main data
                plt.plot(Thetae,
                         P,
    def getData(self, time, model_vars, mdl2stnd, previous_data=None):
        '''
    Name:
      awips_model_base
    Purpose:
      A function to get data from NAM40 model to create HDWX products
    Inputs:
      request    : A DataAccessLayer request object
      time       : List of datatime(s) for data to grab
      model_vars : Dictionary with variables/levels to get
      mdl2stnd   : Dictionary to convert from model variable names
                    to standardized names
    Outputs:
      Returns a dictionary containing all data
    Keywords:
      previous_data : Dictionary with data from previous time step
    '''
        log = logging.getLogger(__name__)
        # Set up function for logger
        initTime, fcstTime = get_init_fcst_times(time[0])
        data = {
            'model': self._request.getLocationNames()[0],
            'initTime': initTime,
            'fcstTime': fcstTime
        }
        # Initialize empty dictionary

        log.info('Attempting to download {} data'.format(data['model']))

        for var in model_vars:  # Iterate over variables in the vars list
            log.debug('Getting: {}'.format(var))
            self._request.setParameters(*model_vars[var]['parameters'])
            # Set parameters for the download request
            self._request.setLevels(*model_vars[var]['levels'])
            # Set levels for the download request

            response = DAL.getGridData(self._request, time)  # Request the data

            for res in response:  # Iterate over all data request responses
                varName = res.getParameter()
                # Get name of the variable in the response
                varLvl = res.getLevel()
                # Get level of the variable in the response
                varName = mdl2stnd[varName]
                # Convert variable name to local standarized name
                if varName not in data:
                    data[varName] = {}
                    # If variable name NOT in data dictionary, initialize new dictionary under key
                data[varName][varLvl] = res.getRawData()
                # Add data under level name
                try:  # Try to
                    unit = units(res.getUnit())
                    # Get units and convert to MetPy units
                except:  # On exception
                    unit = '?'
                    # Set units to ?
                else:  # If get units success
                    data[varName][varLvl] *= unit
                    # Get data and create MetPy quantity by multiplying by units

                log.debug(
                    'Got data for:\n  Var:  {}\n  Lvl:  {}\n  Unit: {}'.format(
                        varName, varLvl, unit))
        data['lon'], data['lat'] = res.getLatLonCoords()
        # Get latitude and longitude values
        data['lon'] *= units('degree')
        # Add units of degree to longitude
        data['lat'] *= units('degree')
        # Add units of degree to latitude

        # Absolute vorticity
        dx, dy = lat_lon_grid_deltas(data['lon'], data['lat'])
        # Get grid spacing in x and y
        uTag = mdl2stnd[model_vars['wind']['parameters'][0]]
        # Get initial tag name for u-wind
        vTag = mdl2stnd[model_vars['wind']['parameters'][1]]
        # Get initial tag name for v-wind
        if (uTag in data) and (
                vTag in data):  # If both tags are in the data structure
            data['abs_vort'] = {}
            # Add absolute vorticity key
            for lvl in model_vars['wind'][
                    'levels']:  # Iterate over all leves in the wind data
                if (lvl in data[uTag]) and (
                        lvl in data[vTag]
                ):  # If given level in both u- and v-wind dictionaries
                    log.debug('Computing absolute vorticity at {}'.format(lvl))
                    data['abs_vort'][ lvl ] = \
                      absolute_vorticity( data[uTag][lvl], data[vTag][lvl],
                                          dx, dy, data['lat'] )
                    # Compute absolute vorticity

        # 1000 MB equivalent potential temperature
        if ('temperature' in data) and (
                'dewpoint'
                in data):  # If temperature AND depoint data were downloaded
            data['theta_e'] = {}
            T, Td = 'temperature', 'dewpoint'
            if ('1000.0MB' in data[T]) and (
                    '1000.0MB' in data[Td]
            ):  # If temperature AND depoint data were downloaded
                log.debug(
                    'Computing equivalent potential temperature at 1000 hPa')
                data['theta_e']['1000.0MB'] = equivalent_potential_temperature(
                    1000.0 * units('hPa'), data[T]['1000.0MB'],
                    data[Td]['1000.0MB'])

            return data
            # MLCAPE
            log.debug('Computing mixed layer CAPE')
            T_lvl = list(data[T].keys())
            Td_lvl = list(data[Td].keys())
            levels = list(set(T_lvl).intersection(Td_lvl))
            levels = [float(lvl.replace('MB', '')) for lvl in levels]
            levels = sorted(levels, reverse=True)

            nLvl = len(levels)
            if nLvl > 0:
                log.debug(
                    'Found {} matching levels in temperature and dewpoint data'
                    .format(nLvl))
                nLat, nLon = data['lon'].shape

                data['MLCAPE'] = np.zeros((
                    nLat,
                    nLon,
                ), dtype=np.float32) * units('J/kg')
                TT = np.zeros((
                    nLvl,
                    nLat,
                    nLon,
                ), dtype=np.float32) * units('degC')
                TTd = np.zeros((
                    nLvl,
                    nLat,
                    nLon,
                ), dtype=np.float32) * units('degC')

                log.debug('Sorting temperature and dewpoint data by level')
                for i in range(nLvl):
                    key = '{:.1f}MB'.format(levels[i])
                    TT[i, :, :] = data[T][key].to('degC')
                    TTd[i, :, :] = data[Td][key].to('degC')

                levels = np.array(levels) * units.hPa
                depth = 100.0 * units.hPa

                log.debug('Iterating over grid boxes to compute MLCAPE')
                for j in range(nLat):
                    for i in range(nLon):
                        try:
                            _, T_parc, Td_parc = mixed_parcel(
                                levels,
                                TT[:, j, i],
                                TTd[:, j, i],
                                depth=depth,
                                interpolate=False,
                            )
                            profile = parcel_profile(levels, T_parc, Td_parc)
                            cape, cin = cape_cin(levels, TT[:, j, i],
                                                 TTd[:, j, i], profile)
                        except:
                            log.warning(
                                'Failed to compute MLCAPE for lon/lat: {}; {}'.
                                format(data['lon'][j, i], data['lat'][j, i]))
                        else:
                            data['MLCAPE'][j, i] = cape
        return data
Beispiel #33
0
skew.plot(p, Td, 'g')

#plots the barbs
my_interval = np.arange(100, 1000, 20) * units('mbar')
ix = resample_nn_1d(p, my_interval)

skew.plot_barbs(p[ix], u[ix], v[ix])
skew.ax.set_ylim(1075, 100)
skew.ax.set_ylabel('Pressure (hPa)')

lcl_pressure, lcl_temperature = mpcalc.lcl(p[0], T[0], Td[0]) #LCL
pwat = mpcalc.precipitable_water(Td, p, 500 * units.hectopascal).to('in') #PWAT
cape, cin = mpcalc.most_unstable_cape_cin(p[:], T[:], Td[:]) #MUCAPE
cape_sfc, cin_sfc = mpcalc.surface_based_cape_cin(p, T, Td) #SBCAPE
prof = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC') #parcel profile
equiv_pot_temp = mpcalc.equivalent_potential_temperature(p, T, Td) #equivalent potential temperature
el_pressure, el_temperature = mpcalc.el(p, T, Td) #elevated level
lfc_pressure, lfc_temperature = mpcalc.lfc(p, T, Td) #LFC

#calculates shear
u_threekm_bulk_shear, v_threekm_bulk_shear = mpcalc.bulk_shear(p, u, v, hgt, bottom = min(hgt), depth = 3000 * units.meter)
threekm_bulk_shear = mpcalc.get_wind_speed(u_threekm_bulk_shear, v_threekm_bulk_shear)
u_onekm_bulk_shear, v_onekm_bulk_shear = mpcalc.bulk_shear(p, u, v, hgt, bottom = min(hgt), depth = 1000 * units.meter)
onekm_bulk_shear = mpcalc.get_wind_speed(u_onekm_bulk_shear, v_onekm_bulk_shear)

#shows the level of the LCL, LFC, and EL.
skew.ax.text(T[0].magnitude, p[0].magnitude + 5, str(int(np.round(T[0].to('degF').magnitude))), fontsize = 'medium', horizontalalignment = 'left', verticalalignment = 'top', color = 'red')
skew.ax.text(Td[0].magnitude, p[0].magnitude + 5, str(int(np.round(Td[0].to('degF').magnitude))), fontsize = 'medium', horizontalalignment = 'right', verticalalignment = 'top', color = 'green')
skew.ax.text(lcl_temperature.magnitude + 5, lcl_pressure.magnitude, "---- LCL", fontsize = 'medium', verticalalignment = 'center')
skew.ax.text(Td[0].magnitude - 10, p[0].magnitude, 'SFC: {}hPa ----'.format(p[0].magnitude), fontsize = 'medium', horizontalalignment = 'right', verticalalignment = 'center', color = 'black')