Example #1
0
def test_scalar():
    """Test potential_temperature accepts scalar values."""
    assert_almost_equal(
        potential_temperature(1000. * units.mbar, 293. * units.kelvin),
        293. * units.kelvin, 4)
    assert_almost_equal(
        potential_temperature(800. * units.mbar, 293. * units.kelvin),
        312.2828 * units.kelvin, 4)
Example #2
0
def pv(input_file):

    # Vars
    grib_vars = ['t','u','v']

    # Load a list of datasets, one for each variable we want
    ds_list = [cfgrib.open_datasets(input_file,backend_kwargs={'filter_by_keys':{'typeOfLevel':'isobaricInhPa','shortName':v},'indexpath':''}) for v in grib_vars]

    # Flatten the list of lists to a single list of datasets
    ds_flat = [x.sel(isobaricInhPa=x.isobaricInhPa[x.isobaricInhPa>=100.0].values) for ds in ds_list for x in ds]

    # Merge the variables into a single dataset
    ds = xr.merge(ds_flat)

    # Add pressure
    ds['p'] = xr.DataArray(ds.isobaricInhPa.values,dims=['isobaricInhPa'],coords={'isobaricInhPa':ds.isobaricInhPa.values},attrs={'units':'hPa'}).broadcast_like(ds['t'])

    # Calculate potential temperature
    ds['theta'] = mpcalc.potential_temperature(ds['p'].metpy.convert_units('Pa'),ds['t'])

    # Compute baroclinic PV
    ds['pv'] = mpcalc.potential_vorticity_baroclinic(ds['theta'],ds['p'].metpy.convert_units('Pa'),ds['u'],ds['v'],latitude=ds.latitude)/(1.0e-6)

    met_data = ds['pv'].sel(isobaricInhPa=slice(float(os.environ.get('PV_LAYER_MAX_PRESSURE',1000.0)),float(os.environ.get('PV_LAYER_MIN_PRESSURE',100.0)))).mean(axis=0).values

    return met_data
Example #3
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)
Example #4
0
def add_metpy(option, filename):
    """
    Adds the variables possible through metpy (theta, pv, n2)
    """
    with xr.load_dataset(filename) as xin:
        if option.theta or option.pv:
            print("Adding potential temperature...")
            xin["pt"] = potential_temperature(xin["pressure"], xin["t"])
            xin["pt"].data = np.array(xin["pt"].data)
            xin["pt"].attrs["units"] = "K"
            xin["pt"].attrs["standard_name"] = VARIABLES["pt"][2]
        if option.pv:
            print("Adding potential vorticity...")
            xin = xin.metpy.assign_crs(grid_mapping_name='latitude_longitude',
                                       earth_radius=6.356766e6)
            xin["pv"] = potential_vorticity_baroclinic(xin["pt"], xin["pressure"], xin["u"], xin["v"])
            xin["pv"].data = np.array(xin["pv"].data * 10 ** 6)
            xin = xin.drop("metpy_crs")
            xin["pv"].attrs["units"] = "kelvin * meter ** 2 / kilogram / second"
            xin["pv"].attrs["standard_name"] = VARIABLES["pv"][2]
            xin["mod_pv"] = xin["pv"] * ((xin["pt"] / 360) ** (-4.5))
            xin["mod_pv"].attrs["standard_name"] = VARIABLES["mod_pv"][2]
        if option.n2:
            print("Adding N2...")
            xin["n2"] = brunt_vaisala_frequency_squared(geopotential_to_height(xin["zh"]), xin["pt"])
            xin["n2"].data = np.array(xin["n2"].data)
            xin["n2"].attrs["units"] = VARIABLES["n2"][1]
            xin["n2"].attrs["standard_name"] = "square_of_brunt_vaisala_frequency_in_air"

        xin.to_netcdf(filename)
Example #5
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
Example #6
0
def potential_temperature(pressure, temperature):
    r"""This method calls the metpy.calc function potential_temperature
        which takes the pint.Quantity objects containing the
        isobaric level value and the temperature at that level
        and produces the corresponding potential temperature 
        with the reference pressure being 1000 millibars.

    """

    return calc.potential_temperature(pressure, temperature)
Example #7
0
def pot_temp(p, t):
    """
    Computes potential temperature in [K] from pressure and temperature.

    Arguments:
    p -- pressure in [Pa]
    t -- temperature in [K]

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

    Returns: potential temperature in [K].
    """
    return mpcalc.potential_temperature(
        units.Pa * p, units.K * t).to("K").m
Example #8
0
def compute_theta(dset, tvar='t'):
    pres = dset['plev'].metpy.unit_array
    theta = mpcalc.potential_temperature(pres[:, None, None], dset[tvar])

    theta = xr.DataArray(theta.magnitude,
                         coords=dset[tvar].coords,
                         attrs={
                             'standard_name': 'Potential Temperature',
                             'units': theta.units
                         },
                         name='theta')

    out = xr.merge([dset, theta])
    out.attrs = dset.attrs

    return out
Example #9
0
def pot_temp(p, t):
    """
    Computes potential temperature in [K] from pressure and temperature.

    Arguments:
    p -- pressure in [Pa]
    t -- temperature in [K]

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

    Returns: potential temperature in [K]. Same dimensions as the inputs.
    """
    p = units.Quantity(p, "Pa")
    t = units.Quantity(t, "K")
    potential_temp = mpcalc.potential_temperature(p, t)
    return potential_temp
Example #10
0
def calc_theta_from_T(T, p):
    """
    Input :
        T : temperature (deg Celsius)
        p : pressure (hPa)
    Output :
        theta : Potential temperature values 
    Function to estimate potential temperature from the
    temperature and pressure in the given dataset. This function uses MetPy's
    functions to get theta:
    (i) mpcalc.potential_temperature()
    
    """
    theta = mpcalc.potential_temperature(p * units.hPa,
                                         T * units.degC).magnitude

    return theta
Example #11
0
def calc_theta_from_T(dataset):
    """
    Input :

        dataset : Dataset

    Output :

        theta : Potential temperature values 

    Function to estimate potential temperature from the
    temperature and pressure in the given dataset. This function uses MetPy's
    functions to get theta:

    (i) mpcalc.potential_temperature()
    
    """
    theta = mpcalc.potential_temperature(dataset.p.values * units.Pa,
                                         dataset.ta.values *
                                         units.kelvin).magnitude

    return theta
Example #12
0
def moist_adiabat(z, SST):
    p = 1000 * np.exp(-9.81 * z / (287. * 270.)) * units.hPa
    Tp = mpcalc.moist_lapse(p, (SST - 1) * units.K)
    qp = 0.8 * mpcalc.saturation_mixing_ratio(p, Tp)

    ztrop1 = 17e3
    ztrop2 = 19e3
    idx1 = np.argmin((z - ztrop1)**2)
    idx2 = np.argmin((z - ztrop2)**2)
    Tp[idx1:idx2] = Tp[idx1]
    Tp[idx2:] = Tp[idx1] + 2e-3 * (z[idx2:] - ztrop2) * units.K
    thetap = mpcalc.potential_temperature(p, Tp)
    thicknesses = [
        mpcalc.thickness_hydrostatic(p, Tp, bottom=p[i], depth=p[i] - p[i + 1])
        / units.m for i in range(len(p) - 1)
    ]
    zp = np.concatenate([[0.], np.cumsum(thicknesses)])

    thetaz = np.interp(z, zp, (thetap / units.K))
    qz = np.interp(z, zp, qp)
    idxs = z < 35000
    return z[idxs], np.array([float(x) for x in thetaz
                              ])[idxs], np.array([float(x) for x in qz])[idxs]
Example #13
0
def test_fahrenheit():
    """Test that potential_temperature handles temperature values in Fahrenheit."""
    assert_almost_equal(potential_temperature(800. * units.mbar, 68. * units.degF),
                        (312.444 * units.kelvin).to(units.degF), 2)
Example #14
0
def test_scalar():
    """Test potential_temperature accepts scalar values."""
    assert_almost_equal(potential_temperature(1000. * units.mbar, 293. * units.kelvin),
                        293. * units.kelvin, 4)
    assert_almost_equal(potential_temperature(800. * units.mbar, 293. * units.kelvin),
                        312.2828 * units.kelvin, 4)
Example #15
0
##############################
# Get the cross section, and convert lat/lon to supplementary coordinates:

cross = cross_section(data, start, end).set_coords(('lat', 'lon'))

##############################
# For this example, we will be plotting potential temperature, relative humidity, and
# tangential/normal winds. And so, we need to calculate those, and add them to the dataset:

cross['rhum'].metpy.convert_units('percent')

temperature, pressure, relative_humidity = xr.broadcast(
    cross['air'], cross['level'], cross['rhum'])

theta = mpcalc.potential_temperature(pressure, temperature)
print(max(theta.flatten()))
print(min(theta.flatten()))

# These calculations return unit arrays, so put those back into DataArrays in our Dataset
cross['Potential_temperature'] = xr.DataArray(theta,
                                              coords=temperature.coords,
                                              dims=temperature.dims,
                                              attrs={'units': theta.units})
cross['rhum'] = xr.DataArray(relative_humidity / 100,
                             coords=relative_humidity.coords,
                             dims=relative_humidity.dims,
                             attrs={'units': relative_humidity.units})

cross['uwnd'].metpy.convert_units('knots')
cross['vwnd'].metpy.convert_units('knots')
Example #16
0
lon_slice = slice(200, 350)
lat_slice = slice(85, 10)

# Grab lat/lon values (GFS will be 1D)
lats = ds.lat.sel(lat=lat_slice).values
lons = ds.lon.sel(lon=lon_slice).values

# Grab the pressure levels and select the data to be imported
# Need all pressure levels for Temperatures, U and V Wind, and Rel. Humidity
# Smooth with the gaussian filter from scipy
pres = ds['isobaric3'].values[:] * units('Pa')

tmpk_var = ds['Temperature_isobaric'].sel(lat=lat_slice,
                                          lon=lon_slice).values[0]
tmpk = mpcalc.smooth_n_point(tmpk_var, 9, 2) * units.K
thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

uwnd_var = ds['u-component_of_wind_isobaric'].sel(lat=lat_slice,
                                                  lon=lon_slice).values[0]
vwnd_var = ds['v-component_of_wind_isobaric'].sel(lat=lat_slice,
                                                  lon=lon_slice).values[0]
uwnd = mpcalc.smooth_n_point(uwnd_var, 9, 2) * (units.meter / units.second)
vwnd = mpcalc.smooth_n_point(vwnd_var, 9, 2) * (units.meter / units.second)

# Create a clean datetime object for plotting based on time of Geopotential heights
vtime = ds.time.data[0].astype('datetime64[ms]').astype('O')

######################################################################
# Use MetPy to compute the baroclinic potential vorticity on all isobaric
# levels and other variables
#
Example #17
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
Example #18
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)
Example #19
0
def test_potential_temperature():
    """Test potential_temperature calculation."""
    temp = np.array([278., 283., 291., 298.]) * units.kelvin
    pres = np.array([900., 500., 300., 100.]) * units.mbar
    real_th = np.array([286.493, 344.961, 410.4335, 575.236]) * units.kelvin
    assert_array_almost_equal(potential_temperature(pres, temp), real_th, 3)
Example #20
0
def test_pot_temp_inhg():
    """Test that potential_temperature can handle pressure not in mb (issue #165)."""
    assert_almost_equal(potential_temperature(29.92 * units.inHg, 29 * units.degC),
                        301.019735 * units.kelvin, 4)
# p) for all radiosonde variables including, Temperature, Dewpoint,
# u-component of the wind, and v-component of the wind.
#

xsect = radisonde_cross_section(stn_list, df)

######################################################################
# Calculate Variables for Plotting
# --------------------------------
#
# Use MetPy to calculate common variables for plotting a cross section,
# specifically potential temperature and mixing ratio
#

potemp = mpcalc.potential_temperature(
    xsect['p_grid'] * units('hPa'),
    xsect['grid_data']['temperature'] * units('degC'))

relhum = mpcalc.relative_humidity_from_dewpoint(
    xsect['grid_data']['temperature'] * units('degC'),
    xsect['grid_data']['dewpoint'] * units('degC'))

mixrat = mpcalc.mixing_ratio_from_relative_humidity(
    relhum, xsect['grid_data']['temperature'] * units('degC'),
    xsect['p_grid'] * units('hPa'))

######################################################################
# Plot Cross Section
# ------------------
#
# Use standard Matplotlib to plot the now 2D cross section grid using the
Example #22
0
def test_potential_temperature():
    """Test potential_temperature calculation."""
    temp = np.array([278., 283., 291., 298.]) * units.kelvin
    pres = np.array([900., 500., 300., 100.]) * units.mbar
    real_th = np.array([286.493, 344.961, 410.4335, 575.236]) * units.kelvin
    assert_array_almost_equal(potential_temperature(pres, temp), real_th, 3)
Example #23
0
PHIS = PHIS / 9.81

# Force PHIS to have same dimensions as Z3
PHISnew1 = np.repeat(PHIS[np.newaxis, :, :], np.shape(Z3)[1], axis=0)
PHISnew = np.repeat(PHISnew1[np.newaxis, :, :, :], np.shape(Z3)[0], axis=0)
print('Shape of Z3:   ', np.shape(Z3))
print('Shape of PHIS: ', np.shape(PHISnew))

# Height agl is then just Z3 - PHISnew
z_agl = (Z3 - PHISnew) * units.meters

# Get potential temperature
P = (pressDS.PRESSURE.values * landMask) * units('Pa')
T = (varsDS.T.values * landMask) * units('K')

potTemp = mpc.potential_temperature(P, T)

# Clear variables from memory that aren't needed anymore
del PHISnew
del PHIS
del Z3
del P
del T
del pressDS
del z3_ds
del topo_ds
del testDF

# --------- Compute gradient richardson number ------
# Compute gradient richardson number
U = (varsDS.U.values) * units('m/s')
Example #24
0
##############################
# Get the cross section, and convert lat/lon to supplementary coordinates:

cross = cross_section(data, start, end)
cross.set_coords(('lat', 'lon'), True)
print(cross)

##############################
# For this example, we will be plotting potential temperature, relative humidity, and
# tangential/normal winds. And so, we need to calculate those, and add them to the dataset:

temperature, pressure, specific_humidity = xr.broadcast(cross['Temperature'],
                                                        cross['isobaric'],
                                                        cross['Specific_humidity'])

theta = mpcalc.potential_temperature(pressure, temperature)
rh = mpcalc.relative_humidity_from_specific_humidity(specific_humidity, temperature, pressure)

# These calculations return unit arrays, so put those back into DataArrays in our Dataset
cross['Potential_temperature'] = xr.DataArray(theta,
                                              coords=temperature.coords,
                                              dims=temperature.dims,
                                              attrs={'units': theta.units})
cross['Relative_humidity'] = xr.DataArray(rh,
                                          coords=specific_humidity.coords,
                                          dims=specific_humidity.dims,
                                          attrs={'units': rh.units})

cross['u_wind'].metpy.convert_units('knots')
cross['v_wind'].metpy.convert_units('knots')
cross['t_wind'], cross['n_wind'] = mpcalc.cross_section_components(cross['u_wind'],
def f(fullname, selected_time):
    fullname_el = fullname.split('/')
    #fullname_el = fullname.split('\\')
    filename = fullname_el[-1]
    filename_el = filename.split('_')
    save_base_dir_name = '../1data/'
    save_dir_name = '{0}{1}/'.format(save_base_dir_name + dir_name, obs_year)
    print('site : {0}'.format(dir_name))

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

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

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

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

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

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

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

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

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

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

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

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

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

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

        except Exception as err:
            write_log(err_log_file, '{4} ::: {0} with {1}{2} on {3}'\
                      .format(err, dir_name, filename, selected_time[:13], datetime.now()))
    print('Thread {0} is finished'.format(selected_time))
    return 0  # Return a dummy value
Example #26
0
        # skew.plot(profP, parcel_prof, 'k', linewidth=2)

        # 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')
TArr = np.array([t1, t2, t3, t4])
RHArr = np.array([rh1, rh2, rh3, rh4])

Tmean = np.nanmean(TArr, 0)
RHmean = np.nanmean(RHArr, 0)
if np.isnan(RHmean).all():
    isRH = 0
else:
    isRH = 1

######################################################
## Calculate thermodymanic and convective variables ##
######################################################

theta = np.array(
    mcalc.potential_temperature(pres * units.mbar,
                                (Tmean + 273.15) * units.kelvin))
Td = np.array(mcalc.dewpoint_rh(Tmean * units.degC, RHmean / 100.))
ws = np.array(
    mcalc.saturation_mixing_ratio(pres * units.mbar,
                                  (Tmean + 273.15) * units.kelvin))
w = np.multiply(RHmean / 100., ws * 1000.)

# check for RH
if isRH:
    lclpres, lcltemp = mcalc.lcl(pres[0] * units.mbar, Tmean[0] * units.degC,
                                 Td[0] * units.degC)
    print 'LCL Pressure: {}'.format(lclpres)
    print 'LCL Temperature: {}'.format(lcltemp)

    # parcel profile
    # determine if there are points sampled above lcl
Example #28
0
                    ###########################################
                    # We will pull the data out of the example dataset into individual variables and
                    # assign units.

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

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

                    df_selected_time[
                        'saturation_vaper_pressure'] = mpcalc.saturation_vapor_pressure(
                            T)
                    df_selected_time[
                        'vaper_pressure'] = mpcalc.saturation_vapor_pressure(
                            Td)
                    VPS = df_selected_time[
                        'saturation_vaper_pressure'].values * units.hPa
                    VP = df_selected_time['vaper_pressure'].values * units.hPa

                    df_selected_time[
                        'saturation_mixing_ratio'] = mpcalc.mixing_ratio(
Example #29
0
PWAT = PWAT_DATA.variables['pr_wtr'][TIME_INDEX, :, :]
QVEC700 = mpcalc.q_vector(U700, V700, T700, 700 * units.mbar, DX, DY)
QC700 = mpcalc.divergence(QVEC700[0], QVEC700[1], DX, DY,
                          dim_order='yx') * (10**18)
QVECX = QVEC700[0]
QVECY = QVEC700[1]
# =============================================================================
# FIG #4: 850: GEOPOTENTIAL HEIGHT, TEMP, WINDS, TEMP-ADVECTION, FRONTOGENESIS
# =============================================================================
H850 = HGT_DATA.variables['hgt'][TIME_INDEX, 2, :, :]
T850 = AIR_DATA.variables['air'][TIME_INDEX, 2, :, :] * units('kelvin')
U850 = UWND_DATA.variables['uwnd'][TIME_INDEX, 2, :, :] * units('m/s')
V850 = VWND_DATA.variables['vwnd'][TIME_INDEX, 2, :, :] * units('m/s')
T_ADV850 = mpcalc.advection(T850 * units.kelvin, [U850, V850], (DX, DY),
                            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)
# =============================================================================
Example #30
0
def test_fahrenheit():
    """Test that potential_temperature handles temperature values in Fahrenheit."""
    assert_almost_equal(potential_temperature(800. * units.mbar, 68. * units.degF),
                        (312.444 * units.kelvin).to(units.degF), 2)
def cross_section(isentlev, num, left_lat, left_lon, right_lat, right_lon):
    """Plot an isentropic cross-section."""
    # get the coordinates of the endpoints for the cross-section
    left_coord = np.array((float(left_lat), float(left_lon)))
    right_coord = np.array((float(right_lat), float(right_lon)))

    # Calculate data for the inset isentropic map
    isent_anal = mcalc.isentropic_interpolation(float(isentlev) * units.kelvin, lev, tmp,
                                                spech, tmpk_out=True)
    isentprs = isent_anal[0]
    isenttmp = isent_anal[1]
    isentspech = isent_anal[2]
    isentrh = mcalc.relative_humidity_from_specific_humidity(isentspech, isenttmp, isentprs)

    # Find index values for the cross section slice
    iright = lat_lon_2d_index(lat, lon, right_coord[0], right_coord[1])
    ileft = lat_lon_2d_index(lat, lon, left_coord[0], left_coord[1])

    # Get the cross-section slice data
    cross_data = mcalc.extract_cross_section(ileft, iright, lat, lon, tmp, uwnd, vwnd, spech,
                                             num=num)
    cross_lat = cross_data[0]
    cross_lon = cross_data[1]
    cross_t = cross_data[2]
    cross_u = cross_data[3]
    cross_v = cross_data[4]
    cross_spech = cross_data[5]

    # Calculate theta and RH on the cross-section
    cross_theta = mcalc.potential_temperature(lev[:, np.newaxis], cross_t)
    cross_rh = mcalc.relative_humidity_from_specific_humidity(cross_spech, cross_t,
                                                              lev[:, np.newaxis])

    # Create figure for ploting
    fig = plt.figure(1, figsize=(17., 12.))

    # Plot the cross section
    ax1 = plt.axes()
    ax1.set_yscale('symlog')
    ax1.grid()
    cint = np.arange(250, 450, 5)

    # Determine whether to label x-axis with lat or lon values
    if np.abs(left_lon - right_lon) > np.abs(left_lat - right_lat):
        cs = ax1.contour(cross_lon, lev[::-1], cross_theta[::-1, :], cint, colors='tab:red')
        cf = ax1.contourf(cross_lon, lev[::-1], cross_rh[::-1, :], range(10, 106, 5),
                          cmap=plt.cm.gist_earth_r)
        ax1.barbs(cross_lon[4::4], lev, cross_u[:, 4::4], cross_v[:, 4::4], length=6)
        plt.xlabel('Longitude (Degrees East)')
    else:
        cs = ax1.contour(cross_lat[::-1], lev[::-1], cross_theta[::-1, ::-1], cint,
                         colors='tab:red')
        cf = ax1.contourf(cross_lat[::-1], lev[::-1], cross_rh[::-1, ::-1], range(10, 106, 5),
                          cmap=plt.cm.gist_earth_r)
        ax1.barbs(cross_lat[::-4], lev, cross_u[:, ::-4], cross_v[:, ::-4], length=6)
        plt.xlim(cross_lat[0], cross_lat[-1])
        plt.xlabel('Latitude (Degrees North)')

    # Label the cross section axes
    plt.clabel(cs, fontsize=10, inline=1, inline_spacing=7,
               fmt='%i', rightside_up=True, use_clabeltext=True)
    cb = plt.colorbar(cf, orientation='horizontal', extend=max, aspect=65, shrink=0.75,
                      pad=0.06, extendrect='True')
    cb.set_label('Relative Humidity', size='x-large')
    plt.ylabel('Pressure (hPa)')
    ax1.set_yticklabels(np.arange(1000, 50, -50))
    plt.ylim(lev[0], lev[-1])
    plt.yticks(np.arange(1000, 50, -50))

    # Add a title
    plt.title(('NARR Isentropic Cross-Section: ' + str(left_coord[0]) + ' N, ' +
               str(left_coord[1]) + ' E  to ' + str(right_coord[0]) + ' N, ' +
               str(right_coord[1]) + ' E'), loc='left')
    plt.title('VALID: {:s}'.format(str(vtimes[0])), loc='right')

    # Add Inset Map
    ax2 = fig.add_axes([0.125, 0.643, 0.25, 0.25], projection=crs)

    # Coordinates to limit map area
    bounds = [(-122., -75., 25., 50.)]

    # Limit extent of inset map
    ax2.set_extent(*bounds, crs=ccrs.PlateCarree())
    ax2.coastlines('50m', edgecolor='black', linewidth=0.75)
    ax2.add_feature(states_provinces, edgecolor='black', linewidth=0.5)

    # Plot the surface
    clevisent = np.arange(0, 1000, 25)
    cs = ax2.contour(tlons, tlats, isentprs[0, :, :], clevisent,
                     colors='k', linewidths=1.0, linestyles='solid')
    plt.clabel(cs, fontsize=10, inline=1, inline_spacing=7,
               fmt='%i', rightside_up=True, use_clabeltext=True)

    # Plot RH
    cf = ax2.contourf(tlons, tlats, isentrh[0, :, :], range(10, 106, 5),
                      cmap=plt.cm.gist_earth_r)

    # Convert endpoints of cross-section line
    left = crs.transform_point(left_coord[1], left_coord[0], ccrs.PlateCarree())
    right = crs.transform_point(right_coord[1], right_coord[0], ccrs.PlateCarree())

    # Plot the cross section line
    plt.plot([left[0], right[0]], [left[1], right[1]], color='r')
    plt.show()
Example #32
0
def PV_Div_uv(initTime=None,
              fhour=6,
              day_back=0,
              model='ECMWF',
              map_ratio=14 / 9,
              zoom_ratio=20,
              cntr_pnt=[104, 34],
              levels=[
                  1000, 950, 925, 900, 850, 800, 700, 600, 500, 400, 300, 250,
                  200, 100
              ],
              lvl_ana=250,
              Global=False,
              south_China_sea=True,
              area=None,
              city=False,
              output_dir=None,
              data_source='MICAPS',
              **kwargs):

    # micaps data directory
    if (area != None):
        south_China_sea = False

    # micaps data directory
    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='')
            ]
        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 = MICAPS_IO.get_model_3D_grid(directory=data_dir[0][0:-1],
                                         filename=filename,
                                         levels=levels,
                                         allExists=False)
        if rh is None:
            return

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

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

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

    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:
            # retrieve data from CIMISS server
            rh = CMISS_IO.cimiss_model_3D_grid(
                data_code=utl.CMISS_data_code(data_source=model,
                                              var_name='RHU'),
                init_time_str='20' + filename[0:8],
                valid_time=fhour,
                fcst_levels=levels,
                fcst_ele="RHU",
                units='%')
            if rh is None:
                return

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

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

            t = CMISS_IO.cimiss_model_3D_grid(
                data_code=utl.CMISS_data_code(data_source=model,
                                              var_name='TEM'),
                init_time_str='20' + filename[0:8],
                valid_time=fhour,
                fcst_levels=levels,
                fcst_ele="TEM",
                units='K')
            if t is None:
                return
            t['data'].values = t['data'].values - 273.15
            t['data'].attrs['units'] = 'C'
        except KeyError:
            raise ValueError('Can not find all data needed')

    if (area != None):
        cntr_pnt, zoom_ratio = utl.get_map_area(area_name=area)

    map_extent = [0, 0, 0, 0]
    map_extent[0] = cntr_pnt[0] - zoom_ratio * 1 * map_ratio
    map_extent[1] = cntr_pnt[0] + zoom_ratio * 1 * map_ratio
    map_extent[2] = cntr_pnt[1] - zoom_ratio * 1
    map_extent[3] = cntr_pnt[1] + zoom_ratio * 1

    delt_x = (map_extent[1] - map_extent[0]) * 0.2
    delt_y = (map_extent[3] - map_extent[2]) * 0.1

    #+ to solve the problem of labels on all the contours
    mask1 = (rh['lon'] >
             map_extent[0] - delt_x) & (rh['lon'] < map_extent[1] + delt_x) & (
                 rh['lat'] > map_extent[2] - delt_y) & (rh['lat'] <
                                                        map_extent[3] + delt_y)

    mask2 = (u['lon'] >
             map_extent[0] - delt_x) & (u['lon'] < map_extent[1] + delt_x) & (
                 u['lat'] > map_extent[2] - delt_y) & (u['lat'] <
                                                       map_extent[3] + delt_y)

    mask3 = (t['lon'] >
             map_extent[0] - delt_x) & (t['lon'] < map_extent[1] + delt_x) & (
                 t['lat'] > map_extent[2] - delt_y) & (t['lat'] <
                                                       map_extent[3] + delt_y)
    #- to solve the problem of labels on all the contours
    rh = rh.where(mask1, drop=True)
    u = u.where(mask2, drop=True)
    v = v.where(mask2, drop=True)
    t = t.where(mask3, drop=True)
    uv = xr.merge([u.rename({'data': 'u'}), v.rename({'data': 'v'})])

    lats = np.squeeze(rh['lat'].values)
    lons = np.squeeze(rh['lon'].values)

    pres = np.array(levels) * 100 * units('Pa')
    tmpk = mpcalc.smooth_n_point(
        (t['data'].values.squeeze() + 273.15), 9, 2) * units('kelvin')
    thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

    uwnd = mpcalc.smooth_n_point(u['data'].values.squeeze(), 9,
                                 2) * units.meter / units.second
    vwnd = mpcalc.smooth_n_point(v['data'].values.squeeze(), 9,
                                 2) * units.meter / units.second

    dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats)

    # Comput the PV on all isobaric surfaces
    pv_raw = mpcalc.potential_vorticity_baroclinic(
        thta, pres[:, None, None], uwnd, vwnd, dx[None, :, :], dy[None, :, :],
        lats[None, :, None] * units('degrees'))
    div_raw = mpcalc.divergence(uwnd,
                                vwnd,
                                dx[None, :, :],
                                dy[None, :, :],
                                dim_order='yx')

    # prepare data
    idx_z1 = list(pres.m).index(((lvl_ana * units('hPa')).to(pres.units)).m)

    pv = rh.copy(deep=True)
    pv['data'].values = np.array(pv_raw).reshape(
        np.append(1,
                  np.array(pv_raw).shape))
    pv['data'].attrs['units'] = str(pv_raw.units)
    pv.attrs['model'] = model
    pv = pv.where(pv['level'] == lvl_ana, drop=True)

    div = u.copy(deep=True)
    div['data'].values = np.array(div_raw).reshape(
        np.append(1,
                  np.array(div_raw).shape))
    div['data'].attrs['units'] = str(div_raw.units)
    div = div.where(div['level'] == lvl_ana, drop=True)

    uv = uv.where(uv['level'] == lvl_ana, drop=True)

    synoptic_graphics.draw_PV_Div_uv(pv=pv,
                                     uv=uv,
                                     div=div,
                                     map_extent=map_extent,
                                     regrid_shape=20,
                                     city=city,
                                     south_China_sea=south_China_sea,
                                     output_dir=output_dir,
                                     Global=Global)
Example #33
0
def test_pot_temp_inhg():
    """Test that potential_temperature can handle pressure not in mb (issue #165)."""
    assert_almost_equal(potential_temperature(29.92 * units.inHg, 29 * units.degC),
                        301.019735 * units.kelvin, 4)
Example #34
0
def calc_param_wrf_par(it):

    #Have copied this function here from calc_param_wrf_par, to use global arrays

    t, param = it
    wg = False

    p_3d = np.moveaxis(np.tile(p, [ta.shape[0], ta.shape[2], ta.shape[3], 1]),
                       [0, 1, 2, 3], [0, 2, 3, 1])
    param = np.array(param)
    param_out = [0] * (len(param))
    for i in np.arange(0, len(param)):
        param_out[i] = np.empty((len(lat), len(lon)))
    if len(param) != len(np.unique(param)):
        ValueError("Each parameter can only appear once in parameter list")
    print(date_list[t])

    start = dt.datetime.now()
    hur_unit = units.percent * hur[t, :, :, :]
    ta_unit = units.degC * ta[t, :, :, :]
    dp_unit = units.degC * dp[t, :, :, :]
    p_unit = units.hectopascals * p_3d[t, :, :, :]
    q_unit = mpcalc.mixing_ratio_from_relative_humidity(hur_unit,\
     ta_unit,p_unit)
    theta_unit = mpcalc.potential_temperature(p_unit, ta_unit)
    q = np.array(q_unit)

    ml_inds = ((p_3d[t] <= ps[t]) & (p_3d[t] >= (ps[t] - 100)))
    ml_ta_avg = np.ma.masked_where(~ml_inds, ta[t]).mean(axis=0).data
    ml_q_avg = np.ma.masked_where(~ml_inds, q).mean(axis=0).data
    ml_hgt_avg = np.ma.masked_where(~ml_inds, hgt[t]).mean(axis=0).data
    ml_p3d_avg = np.ma.masked_where(~ml_inds, p_3d[t]).mean(axis=0).data
    ml_ta_arr = np.insert(ta[t], 0, ml_ta_avg, axis=0)
    ml_q_arr = np.insert(q, 0, ml_q_avg, axis=0)
    ml_hgt_arr = np.insert(hgt[t], 0, ml_hgt_avg, axis=0)
    ml_p3d_arr = np.insert(p_3d[t], 0, ml_p3d_avg, axis=0)
    a,temp1,temp2 = np.meshgrid(np.arange(ml_p3d_arr.shape[0]) ,\
      np.arange(ml_p3d_arr.shape[1]), np.arange(ml_p3d_arr.shape[2]))
    sort_inds = np.flipud(
        np.lexsort([np.swapaxes(a, 1, 0), ml_p3d_arr], axis=0))
    ml_ta_arr = np.take_along_axis(ml_ta_arr, sort_inds, axis=0)
    ml_p3d_arr = np.take_along_axis(ml_p3d_arr, sort_inds, axis=0)
    ml_hgt_arr = np.take_along_axis(ml_hgt_arr, sort_inds, axis=0)
    ml_q_arr = np.take_along_axis(ml_q_arr, sort_inds, axis=0)
    cape3d_mlavg = wrf.cape_3d(ml_p3d_arr,ml_ta_arr + 273.15,\
     ml_q_arr,ml_hgt_arr,terrain,ps[t,:,:],False,meta=False,missing=0)
    ml_cape = np.ma.masked_where(~((ml_ta_arr==ml_ta_avg) & (ml_p3d_arr==ml_p3d_avg)),\
     cape3d_mlavg.data[0]).max(axis=0).filled(0)
    ml_cin = np.ma.masked_where(~((ml_ta_arr==ml_ta_avg) & (ml_p3d_arr==ml_p3d_avg)),\
     cape3d_mlavg.data[1]).max(axis=0).filled(0)

    cape3d = wrf.cape_3d(p_3d[t,:,:,:],ta[t,:,:,:]+273.15,q,hgt[t,:,:,:],terrain,ps[t,:,:],\
     True,meta=False,missing=0)
    cape = cape3d.data[0]
    cin = cape3d.data[1]
    cape[p_3d[t] > ps[t] - 25] = np.nan
    cin[p_3d[t] > ps[t] - 25] = np.nan
    mu_cape_inds = np.nanargmax(cape, axis=0)
    mu_cape = mu_cape_inds.choose(cape)
    mu_cin = mu_cape_inds.choose(cin)
    cape_2d = wrf.cape_2d(p_3d[t,:,:,:],ta[t,:,:,:]+273.15,q\
     ,hgt[t,:,:,:],terrain,ps[t,:,:],True,meta=False,missing=0)
    lcl = cape_2d[2].data
    lfc = cape_2d[3].data

    del hur_unit, dp_unit, theta_unit, ml_inds, ml_ta_avg, ml_q_avg, \
     ml_hgt_avg, ml_p3d_avg, ml_ta_arr, ml_q_arr, ml_hgt_arr, ml_p3d_arr, a, temp1, temp2,\
     sort_inds, cape3d_mlavg, cape3d, cape, cin, cape_2d

    if "relhum850-500" in param:
        param_ind = np.where(param == "relhum850-500")[0][0]
        param_out[param_ind] = get_mean_var_p(hur[t], p, 850, 500)
    if "relhum1000-700" in param:
        param_ind = np.where(param == "relhum1000-700")[0][0]
        param_out[param_ind] = get_mean_var_p(hur[t], p, 1000, 700)
    if "mu_cape" in param:
        param_ind = np.where(param == "mu_cape")[0][0]
        param_out[param_ind] = mu_cape
    if "ml_cape" in param:
        param_ind = np.where(param == "ml_cape")[0][0]
        param_out[param_ind] = ml_cape
    if "s06" in param:
        param_ind = np.where(param == "s06")[0][0]
        s06 = get_shear_hgt(ua[t],va[t],hgt[t],0,6000,\
         uas[t],vas[t])
        param_out[param_ind] = s06
    if "s03" in param:
        param_ind = np.where(param == "s03")[0][0]
        s03 = get_shear_hgt(ua[t],va[t],hgt[t],0,3000,\
         uas[t],vas[t])
        param_out[param_ind] = s03
    if "s01" in param:
        param_ind = np.where(param == "s01")[0][0]
        s01 = get_shear_hgt(ua[t],va[t],hgt[t],0,1000,\
         uas[t],vas[t])
        param_out[param_ind] = s01
    if "s0500" in param:
        param_ind = np.where(param == "s0500")[0][0]
        param_out[param_ind] = get_shear_hgt(ua[t],va[t],hgt[t],0,500,\
         uas[t],vas[t])
    if "lr1000" in param:
        param_ind = np.where(param == "lr1000")[0][0]
        lr1000 = get_lr_hgt(ta[t], hgt[t], 0, 1000)
        param_out[param_ind] = lr1000
    if "mu_cin" in param:
        param_ind = np.where(param == "mu_cin")[0][0]
        param_out[param_ind] = mu_cin
    if "lcl" in param:
        param_ind = np.where(param == "lcl")[0][0]
        temp_lcl = np.copy(lcl)
        temp_lcl[temp_lcl <= 0] = np.nan
        param_out[param_ind] = temp_lcl
    if "ml_cin" in param:
        param_ind = np.where(param == "ml_cin")[0][0]
        param_out[param_ind] = ml_cin
    if "srh01" in param:
        param_ind = np.where(param == "srh01")[0][0]
        srh01 = get_srh(ua[t], va[t], hgt[t], 1000, True, 850, 700, p)
        param_out[param_ind] = srh01
    if "srh03" in param:
        srh03 = get_srh(ua[t], va[t], hgt[t], 3000, True, 850, 700, p)
        param_ind = np.where(param == "srh03")[0][0]
        param_out[param_ind] = srh03
    if "srh06" in param:
        param_ind = np.where(param == "srh06")[0][0]
        srh06 = get_srh(ua[t], va[t], hgt[t], 6000, True, 850, 700, p)
        param_out[param_ind] = srh06
    if "ship" in param:
        if "s06" not in param:
            raise NameError("To calculate ship, s06 must be included")
        param_ind = np.where(param == "ship")[0][0]
        muq = mu_cape_inds.choose(q)
        ship = get_ship(mu_cape, np.copy(muq), ta[t], ua[t], va[t], hgt[t], p,
                        np.copy(s06))
        param_out[param_ind] = ship
    if "mmp" in param:
        param_ind = np.where(param == "mmp")[0][0]
        param_out[param_ind] = get_mmp(ua[t],va[t],uas[t],vas[t],\
         mu_cape,ta[t],hgt[t])
    if "scp" in param:
        if "srh03" not in param:
            raise NameError("To calculate ship, srh03 must be included")
        param_ind = np.where(param == "scp")[0][0]
        scell_pot = get_supercell_pot(mu_cape,ua[t],va[t],hgt[t],ta_unit,p_unit,\
          q_unit,srh03)
        param_out[param_ind] = scell_pot
    if "stp" in param:
        if "srh01" not in param:
            raise NameError("To calculate stp, srh01 must be included")
        param_ind = np.where(param == "stp")[0][0]
        stp = get_tornado_pot(ml_cape,np.copy(lcl),np.copy(ml_cin),ua[t],va[t],p_3d[t],hgt[t],p,\
         np.copy(srh01))
        param_out[param_ind] = stp
    if "vo10" in param:
        param_ind = np.where(param == "vo10")[0][0]
        x, y = np.meshgrid(lon, lat)
        dx, dy = mpcalc.lat_lon_grid_deltas(x, y)
        vo10 = get_vo(uas[t], vas[t], dx, dy)
        param_out[param_ind] = vo10
    if "conv10" in param:
        param_ind = np.where(param == "conv10")[0][0]
        x, y = np.meshgrid(lon, lat)
        dx, dy = mpcalc.lat_lon_grid_deltas(x, y)
        param_out[param_ind] = get_conv(uas[t], vas[t], dx, dy)
    if "conv1000-850" in param:
        levs = np.where((p <= 1001) & (p >= 849))[0]
        param_ind = np.where(param == "conv1000-850")[0][0]
        x, y = np.meshgrid(lon, lat)
        dx, dy = mpcalc.lat_lon_grid_deltas(x, y)
        param_out[param_ind] = \
         np.mean(np.stack([get_conv(ua[t,i],va[t,i],dx,dy) for i in levs]),axis=0)
    if "conv800-600" in param:
        levs = np.where((p <= 801) & (p >= 599))[0]
        param_ind = np.where(param == "conv800-600")[0][0]
        x, y = np.meshgrid(lon, lat)
        dx, dy = mpcalc.lat_lon_grid_deltas(x, y)
        param_out[param_ind] = \
         np.mean(np.stack([get_conv(ua[t,i],va[t,i],dx,dy) for i in levs]),axis=0)
    if "non_sc_stp" in param:
        if "vo10" not in param:
            raise NameError("To calculate non_sc_stp, vo must be included")
        if "lr1000" not in param:
            raise NameError("To calculate non_sc_stp, lr1000 must be included")
        param_ind = np.where(param == "non_sc_stp")[0][0]
        non_sc_stp = get_non_sc_tornado_pot(ml_cape,ml_cin,np.copy(lcl),ua[t],va[t],\
         uas[t],vas[t],p_3d[t],ta[t],hgt[t],p,vo10,lr1000)
        param_out[param_ind] = non_sc_stp
    if "cape*s06" in param:
        param_ind = np.where(param == "cape*s06")[0][0]
        cs6 = ml_cape * np.power(s06, 1.67)
        param_out[param_ind] = cs6
    if "td850" in param:
        param_ind = np.where(param == "td850")[0][0]
        td850 = get_td_diff(ta[t], dp[t], p_3d[t], 850)
        param_out[param_ind] = td850
    if "td800" in param:
        param_ind = np.where(param == "td800")[0][0]
        param_out[param_ind] = get_td_diff(ta[t], dp[t], p_3d[t], 800)
    if "td950" in param:
        param_ind = np.where(param == "td950")[0][0]
        param_out[param_ind] = get_td_diff(ta[t], dp[t], p_3d[t], 950)
    if "wg" in param:
        try:
            param_ind = np.where(param == "wg")[0][0]
            param_out[param_ind] = wg[t]
        except ValueError:
            print("wg field expected, but not parsed")
    if "dcape" in param:
        param_ind = np.where(param == "dcape")[0][0]
        dcape = np.nanmax(get_dcape(p_3d[t], ta[t], hgt[t], p, ps[t]), axis=0)
        param_out[param_ind] = dcape
    if "mlm" in param:
        param_ind = np.where(param == "mlm")[0][0]
        mlm_u, mlm_v = get_mean_wind(ua[t], va[t], hgt[t], 800, 600, False,
                                     None, "plevels", p)
        mlm = np.sqrt(np.square(mlm_u) + np.square(mlm_v))
        param_out[param_ind] = mlm
    if "dlm" in param:
        param_ind = np.where(param == "dlm")[0][0]
        dlm_u, dlm_v = get_mean_wind(ua[t], va[t], hgt[t], 1000, 500, False,
                                     None, "plevels", p)
        dlm = np.sqrt(np.square(dlm_u) + np.square(dlm_v))
        param_out[param_ind] = dlm
    if "dlm+dcape" in param:
        param_ind = np.where(param == "dlm+dcape")[0][0]
        dlm_dcape = dlm + np.sqrt(2 * dcape)
        param_out[param_ind] = dlm_dcape
    if "mlm+dcape" in param:
        param_ind = np.where(param == "mlm+dcape")[0][0]
        mlm_dcape = mlm + np.sqrt(2 * dcape)
        param_out[param_ind] = mlm_dcape
    if "dcape*cs6" in param:
        param_ind = np.where(param == "dcape*cs6")[0][0]
        param_out[param_ind] = (dcape / 980.) * (cs6 / 20000)
    if "dlm*dcape*cs6" in param:
        param_ind = np.where(param == "dlm*dcape*cs6")[0][0]
        param_out[param_ind] = (dlm_dcape / 30.) * (cs6 / 20000)
    if "mlm*dcape*cs6" in param:
        param_ind = np.where(param == "mlm*dcape*cs6")[0][0]
        param_out[param_ind] = (mlm_dcape / 30.) * (cs6 / 20000)
    if "dcp" in param:
        param_ind = np.where(param == "dcp")[0][0]
        param_out[param_ind] = (dcape / 980) * (mu_cape /
                                                2000) * (s06 / 10) * (dlm / 8)
    if "mf" in param:
        param_ind = np.where(param == "mf")[0][0]
        mf = ((ml_cape > 120) & (dcape > 350) & (mlm < 26))
        mf = mf * 1.0
        param_out[param_ind] = mf
    if "sf" in param:
        param_ind = np.where(param == "sf")[0][0]
        sf = ((s06 >= 30) & (dcape < 500) & (mlm >= 26))
        sf = sf * 1.0
        param_out[param_ind] = sf
    if "cond" in param:
        param_ind = np.where(param == "cond")[0][0]
        cond = (sf == 1.0) | (mf == 1.0)
        cond = cond * 1.0
        param_out[param_ind] = cond

    return param_out
Example #35
0
def PV_Div_uv(initial_time=None, fhour=6, day_back=0,model='ECMWF',
    map_ratio=19/9,zoom_ratio=20,cntr_pnt=[102,34],
    levels=[1000, 950, 925, 900, 850, 800, 700,600,500,400,300,250,200,100],lvl_ana=250,
    Global=False,
    south_China_sea=True,area = '全国',city=False,output_dir=None
     ):

    # 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='')]
    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

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

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

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

    # 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)

    lats = np.squeeze(rh['lat'].values)
    lons = np.squeeze(rh['lon'].values)

    pres = np.array(levels)*100 * units('Pa')
    tmpk = mpcalc.smooth_n_point(t['data'].values.squeeze(), 9, 2)*units('degC')
    thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

    uwnd = mpcalc.smooth_n_point(u['data'].values.squeeze(), 9, 2)*units.meter/units.second
    vwnd = mpcalc.smooth_n_point(v['data'].values.squeeze(), 9, 2)*units.meter/units.second

    dx, dy = mpcalc.lat_lon_grid_deltas(lons, lats)

    # Comput the PV on all isobaric surfaces
    pv = mpcalc.potential_vorticity_baroclinic(thta, pres[:, None, None], uwnd, vwnd,
                                            dx[None, :, :], dy[None, :, :],
                                            lats[None, :, None] * units('degrees'))
    div = mpcalc.divergence(uwnd, vwnd, dx[None, :, :], dy[None, :, :], dim_order='yx')

    # prepare data
    idx_z1 = list(pres.m).index(((lvl_ana * units('hPa')).to(pres.units)).m)
    if(area != None):
        cntr_pnt,zoom_ratio=utl.get_map_area(area_name=area)

    map_extent=[0,0,0,0]
    map_extent[0]=cntr_pnt[0]-zoom_ratio*1*map_ratio
    map_extent[1]=cntr_pnt[0]+zoom_ratio*1*map_ratio
    map_extent[2]=cntr_pnt[1]-zoom_ratio*1
    map_extent[3]=cntr_pnt[1]+zoom_ratio*1

    delt_x=(map_extent[1]-map_extent[0])*0.2
    delt_y=(map_extent[3]-map_extent[2])*0.1

    #+ to solve the problem of labels on all the contours
    idx_x1 = np.where((lons > map_extent[0]-delt_x) & 
        (lons < map_extent[1]+delt_x))
    idx_y1 = np.where((lats > map_extent[2]-delt_y) & 
        (lats < map_extent[3]+delt_y))
    #- to solve the problem of labels on all the contours
    init_time = u.coords['forecast_reference_time'].values
    pv = {
        'lon': lons[idx_x1],
        'lat': lats[idx_y1],
        'data': np.array(pv)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'lev':str(lvl_ana),
        'model':model,
        'fhour':fhour,
        'init_time':init_time}
    uv = {
        'lon': lons[idx_x1],
        'lat': lats[idx_y1],
        'udata': np.array(uwnd)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'vdata': np.array(vwnd)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'lev':str(lvl_ana)}
    div = {
        'lon': lons[idx_x1],
        'lat': lats[idx_y1],
        'data': np.array(div)[idx_z1,idx_y1[0][0]:(idx_y1[0][-1]+1),idx_x1[0][0]:(idx_x1[0][-1]+1)],
        'lev':str(lvl_ana)}

    synoptic_graphics.draw_PV_Div_uv(
        pv=pv, uv=uv, div=div,
        map_extent=map_extent, regrid_shape=20,
        city=city,south_China_sea=south_China_sea,
        output_dir=output_dir,Global=Global)