Пример #1
0
    def _plot_profile(self, skew):

        profiles = self.atmo_profiles  # dictionary
        pres = profiles.get('pres').get('data')
        temp = profiles.get('temp').get('data')
        sphum = profiles.get('sphum').get('data')

        dewpt = mpcalc.dewpoint_from_specific_humidity(sphum, temp,
                                                       pres).to('degF')

        # Pressure vs temperature
        skew.plot(pres, temp, 'r', linewidth=1.5)

        # Pressure vs dew point temperature
        skew.plot(pres, dewpt, 'blue', linewidth=1.5)

        # Compute parcel profile and plot it
        parcel_profile = mpcalc.parcel_profile(pres, temp[0],
                                               dewpt[0]).to('degC')
        skew.plot(
            pres,
            parcel_profile,
            'orange',
            linestyle='dashed',
            linewidth=1.2,
        )
Пример #2
0
def test_dewpoint_specific_humidity():
    """Test relative humidity from specific humidity."""
    p = 1013.25 * units.mbar
    temperature = 20. * units.degC
    q = 0.012 * units.dimensionless
    td = dewpoint_from_specific_humidity(q, temperature, p)
    assert_almost_equal(td, 16.973 * units.degC, 3)
Пример #3
0
def test_dewpoint_specific_humidity():
    """Test relative humidity from specific humidity."""
    p = 1013.25 * units.mbar
    temperature = 20. * units.degC
    q = 0.012 * units.dimensionless
    td = dewpoint_from_specific_humidity(q, temperature, p)
    assert_almost_equal(td, 16.973 * units.degC, 3)
Пример #4
0
    def _write_profile(self, csv_path):

        profiles = self.atmo_profiles  # dictionary
        pres = profiles.get('pres').get('data')
        u = profiles.get('u').get('data')
        v = profiles.get('v').get('data')
        temp = profiles.get('temp').get('data').to('degC')
        sphum = profiles.get('sphum').get('data')

        dewpt = np.array(
            mpcalc.dewpoint_from_specific_humidity(sphum, temp,
                                                   pres).to('degC'))
        wspd = np.array(mpcalc.wind_speed(u, v))
        wdir = np.array(mpcalc.wind_direction(u, v))

        pres = np.array(pres)
        temp = np.array(temp)

        profile = pd.DataFrame({
            'LEVEL': pres,
            'TEMP': temp,
            'DWPT': dewpt,
            'WDIR': wdir,
            'WSPD': wspd,
        })

        profile.to_csv(csv_path, index=False, float_format="%10.2f")
Пример #5
0
def adjust_dew_point_Belcher(tmy, df_c0, df_cf, T_fmy):
    Tdew_fmy = np.array([])

    # Grab monthly means
    temp1 = df_cf.groupby(['month']).mean().reset_index()
    tempt = df_c0.groupby(['month']).mean().reset_index()

    # Scaling
    ahuss = months2hrs((temp1.huss_c / tempt.huss))
    #ahuss = months2hrs( 1 + (temp1.huss - tempt.huss) )

    # FMY Specific Humidity
    huss_fmy = ahuss * tmy.huss

    #Force high values down by finding specific humidity for 100% relative humidity
    #    saturation_huss = mpcalc.specific_humidity_from_mixing_ratio(
    #            mpcalc.mixing_ratio_from_relative_humidity(1.00, T_fmy * units.degC, tmy.press * units.mbar)).magnitude;
    #    huss_fmy[huss_fmy > saturation_huss] = saturation_huss[huss_fmy > saturation_huss];
    #
    #    #Force low values up by finding specific humidity for 0% relative humidity
    #    dry_huss = mpcalc.specific_humidity_from_mixing_ratio(
    #            mpcalc.mixing_ratio_from_relative_humidity(0.00, T_fmy * units.degC, tmy.press * units.mbar)).magnitude;
    #    huss_fmy[huss_fmy < dry_huss] = dry_huss[huss_fmy < dry_huss];

    # FMY dew point
    Tdew_fmy = mpcalc.dewpoint_from_specific_humidity(
        huss_fmy, T_fmy * units.degC, tmy.press * units.mbar).magnitude

    #Force high values down
    Tdew_fmy[Tdew_fmy > T_fmy] = T_fmy[Tdew_fmy > T_fmy]

    return (Tdew_fmy)
Пример #6
0
def thermo_plots(pressure, temperature, mixing_ratio):
    """"
    plots for vertical profiles of temperature, dewpoint, mixing ratio and relative humidity.
    
    Parameters
    ----------
    pressure : array-like
            Atmospheric pressure profile (surface to TOA)
    temperature: array-like
            Atmospheric temperature profile (surface to TOA)
    dewpoint: array-like
            Atmospheric dewpoint profile (surface to TOA)    
    Returns
    -------
    """
    p = pressure * units('mbar')
    q = mixing_ratio * units('kilogram/kilogram')
    T = temperature * units('degC')

    Td = mpcalc.dewpoint_from_specific_humidity(q, T, p)  # dewpoint
    Tp = mpcalc.parcel_profile(p, T[0], Td[0])  # parcel

    plt.figure(figsize=(12, 5))

    lev = find_nearest(p.magnitude, 100)
    plt.subplot(1, 3, 1)
    plt.plot(T[:lev], p[:lev], '-ob')
    plt.plot(Td[:lev], p[:lev], '-og')
    plt.plot(Tp[:lev], p[:lev], '-or')
    plt.xlabel('Temperature [C]', fontsize=12)
    plt.ylabel('Pressure [hpa]', fontsize=12)
    plt.gca().invert_yaxis()
    plt.legend(['Temp', 'Temp_Dew', 'Temp_Parcel'], loc=1)
    plt.grid()

    qs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T), p)
    # Relative humidity
    RH = q / qs * 100  # Relative humidity

    plt.subplot(1, 3, 2)
    plt.plot(q[:lev], p[:lev], '-og')
    plt.xlabel('Mixing ratio [kg/kg]', fontsize=12)
    plt.gca().invert_yaxis()
    plt.grid()

    plt.subplot(1, 3, 3)
    plt.plot(RH[:lev], p[:lev], '-og')
    plt.xlabel('Relative humiduty [%]', fontsize=12)
    plt.gca().invert_yaxis()
    plt.grid()

    plt.tight_layout()
    return (plt)
Пример #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]
Пример #8
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
Пример #9
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
Пример #10
0
def read_merra2(domain,times,pres=True,delta_t=1):
	#Read 3-hourly MERRA2 pressure level/surface data

	if len(times) > 1:
		date_list = date_seq(times,"hours",delta_t)
	else:
		date_list = times

	files_3d = []; files_2d = []
	for d in date_list:
		files_3d.append(glob.glob("/g/data/rr7/MERRA2/raw/M2I3NPASM.5.12.4/"+d.strftime("%Y")+"/"+d.strftime("%m")+"/MERRA2*"+d.strftime("%Y%m%d")+"*.nc4")[0])
		files_2d.append(glob.glob("/g/data/ua8/MERRA2/1hr/M2I1NXASM.5.12.4/"+d.strftime("%Y")+"/"+d.strftime("%m")+"/MERRA2*"+d.strftime("%Y%m%d")+"*.nc4")[0])
	files_3d = np.unique(files_3d)
	files_2d = np.unique(files_2d)

	f3d = xr.open_mfdataset(files_3d, combine="by_coords").sel({"time":date_list, "lev":slice(1000,100), "lon":slice(domain[2], domain[3]), "lat":slice(domain[0], domain[1])})
	f2d = xr.open_mfdataset(files_2d, combine="by_coords").sel({"time":date_list, "lon":slice(domain[2], domain[3]), "lat":slice(domain[0], domain[1])})

	ta_file = f3d["T"]; z_file = f3d["H"]; ua_file = f3d["U"]; va_file = f3d["V"]; hur_file = f3d["RH"]
	uas_file = f2d["U10M"]; vas_file = f2d["V10M"]; hus_file = f2d["QV2M"]; tas_file = f2d["T2M"]; ps_file = f2d["PS"]

	ta = ta_file.values - 273.15
	ua = ua_file.values
	va = va_file.values
	hgt = z_file.values
	hur = hur_file.values * 100
	hur[hur<0] = 0
	hur[hur>100] = 100
	dp = get_dp(ta,hur)
	uas = uas_file.values
	vas = vas_file.values
	tas = tas_file.values - 273.15
	ps = ps_file.values / 100
	ta2d = np.array(mpcalc.dewpoint_from_specific_humidity(hus_file.values, tas*units.units.degC, \
                    ps*units.units.hectopascal))
	terrain = f3d["PHIS"].isel({"time":0}).values / 9.8 
	lon = f2d["lon"].values
	lat = f2d["lat"].values
	p = f3d["lev"].values

	return [ta,dp,hur,hgt,terrain,p,ps,ua,va,uas,vas,tas,ta2d,lon,lat,date_list]
Пример #11
0
def load_weather_model_sounding(latitude, longitude, valid_time):
    with tracer.span(name="latest_run"):
        model = "icon-eu"
        run = latest_run(model, valid_time)

    http_session = session()

    with ThreadPoolExecutor(max_workers=config.parameter_all_levels_workers) as executor:
        p_future = executor.submit(parameter_all_levels, model, run, "p", latitude, longitude, session=http_session)
        T_future = executor.submit(parameter_all_levels, model, run, "T", latitude, longitude, session=http_session)
        QV_future = executor.submit(parameter_all_levels, model, run, "QV", latitude, longitude, session=http_session)
        U_future = executor.submit(parameter_all_levels, model, run, "U", latitude, longitude, session=http_session)
        V_future = executor.submit(parameter_all_levels, model, run, "V", latitude, longitude, session=http_session)
        HHL_future = executor.submit(parameter_all_levels, model, run, "HHL", latitude, longitude, "time_invariant", session=http_session)

    # Pressure Pa
    p_raw = p_future.result()
    p = p_raw.data

    # Temperature K
    T = T_future.result().data

    # Specific Humidty kg/kg
    QV = QV_future.result().data

    # Dewpoint K
    Td = mpcalc.dewpoint_from_specific_humidity(QV * units("kg/kg"), T * units.K, p * units.Pa)

    # Wind m/s
    U = U_future.result().data
    V = V_future.result().data

    # Height above MSL for model level
    HHL = HHL_future.result().data

    meta_data = WeatherModelSoundingMetaData(p_raw.model_time, p_raw.valid_time)

    return WeatherModelSounding(latitude, longitude, p, T, QV, Td, U, V, HHL, meta_data)
Пример #12
0
    model_time = data['hhl']['model_time']
    valid_time = data['hhl']['valid_time']

    print(
        f"model={model}\nmodel_time={model_time}\nvalid_time={valid_time}\nlat={lat} lon={lon}\n")

    print(f"hhl\tHoehe\t\tTemp\t\tTau\t\t\trel Hum\t\t\tDruck\t\t\t\t\tWind\t\t\tWind aus")

    for i in range(top_level - 1, base_level - 1):
        t = data['t']['data'][i] * units.K
        p = (data['p']['data'][i]) * units.Pa
        qv = data['qv']['data'][i] * units("kg/kg")
        h = data['hhl']['data'][i] * units.meter
        u = data['u']['data'][i] * units('m/s')
        v = data['v']['data'][i] * units('m/s')

        # Dewpoint K
        dewpt = mpcalc.dewpoint_from_specific_humidity(qv, t, p)

        # relative humidity
        relhum = mpcalc.relative_humidity_from_dewpoint(t, dewpt)

        celsius = t.to('degC')
        ms = mpcalc.wind_speed(u, v)
        wdir = mpcalc.wind_direction(u, v, convention='from')

        dp = p.to('hPa')

        print(f"{i:-2d}\t{h:~5.1f}\t{celsius:~5.1f}\t{dewpt:~5.1f}\t{relhum:~%}\t{dp:6.1f}\t{ms:~3.1f}\t{wdir:3.0f}")
Пример #13
0
specific_humidity_RA = RA_data['specific_humidity_gkg-1']

# relative humidity, differentiate between water and ice
rhw, rhi = mr2rh(temp_degC, specific_humidity_RA, p_1)
RH_RA = np.zeros(len(rhw))
ind_tresh = RA_data.index[RA_data.altitude_m > 5000][0]
RH_RA[0:ind_tresh] = rhw[0:ind_tresh]
RH_RA[ind_tresh:-1] = rhi[ind_tresh:-1]
RH_RA = RH_RA[0:len(RH_RA)]

p_1 = p_1.values * units.hPa
temp_degC = temp_degC.values * units.degC

# calculate dew point temperature
specific_humidity_RA = specific_humidity_RA.values * units('g/kg')
temp_d_degC = cc.dewpoint_from_specific_humidity(specific_humidity_RA,
                                                 temp_degC, p_1)
RA_data.dew_point_degC = temp_d_degC
RA_data.temperature_degC = RA_data.temperature_K - 273.15

##########################################
## E) RM: Radiometer
##########################################
RM_data = xr.open_dataset(
    RM_archive + '/radiometer_06610_concat_filtered_0.nc').to_dataframe()
RM_data = RM_data[RM_data.time_YMDHMS_1.dt.month == RS_time.month]
RM_data = RM_data[RM_data.time_YMDHMS_1.dt.day == RS_time.day]
date = nearest(RM_data.time_YMDHMS_1, RS_time)
RM_data = RM_data[RM_data.time_YMDHMS_1 == date]

RM_data["time_YMDHMS"] = RM_data.time_YMDHMS_1.dt.round('30min').values
#RM_data['pressure_hPa'] = '0'
Пример #14
0
def read_cmip(model,
              experiment,
              ensemble,
              year,
              domain,
              cmip_ver=5,
              group="",
              al33=False,
              ver6hr="",
              ver3hr="",
              project="CMIP"):

    if cmip_ver == 5:

        #Get CMIP5 file paths

        if al33:
            #NOTE unknown behaviour for al33 directories with multiple versions

            if group == "":
                raise ValueError("Group required")
            if ver6hr == "":
                ver6hr = "v*"
            if ver3hr == "":
                ver3hr = "v*"

            hus_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/6hr/atmos/6hrLev/"+ensemble+"/"+ver6hr+"/hus/*6hrLev*"))
            ta_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/6hr/atmos/6hrLev/"+ensemble+"/"+ver6hr+"/ta/*6hrLev*"))
            ua_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/6hr/atmos/6hrLev/"+ensemble+"/"+ver6hr+"/ua/*6hrLev*"))
            va_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/6hr/atmos/6hrLev/"+ensemble+"/"+ver6hr+"/va/*6hrLev*"))

            huss_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/3hr/atmos/3hr/"+ensemble+"/"+ver3hr+"/huss/*"))
            tas_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/3hr/atmos/3hr/"+ensemble+"/"+ver3hr+"/tas/*"))
            uas_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/3hr/atmos/3hr/"+ensemble+"/"+ver3hr+"/uas/*"))
            vas_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/3hr/atmos/3hr/"+ensemble+"/"+ver3hr+"/vas/*"))
            ps_files = np.sort(glob.glob("/g/data/al33/replicas/CMIP5/combined/"+\
                 group+"/"+model+"/"+experiment+\
                 "/3hr/atmos/3hr/"+ensemble+"/"+ver3hr+"/ps/*"))

        else:

            hus_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/6hr/atmos/"+ensemble+"/hus/latest/*6hrLev*"))
            ta_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/6hr/atmos/"+ensemble+"/ta/latest/*6hrLev*"))
            ua_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/6hr/atmos/"+ensemble+"/ua/latest/*6hrLev*"))
            va_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/6hr/atmos/"+ensemble+"/va/latest/*6hrLev*"))

            huss_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/3hr/atmos/"+ensemble+"/huss/latest/*"))
            tas_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/3hr/atmos/"+ensemble+"/tas/latest/*"))
            uas_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/3hr/atmos/"+ensemble+"/uas/latest/*"))
            vas_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/3hr/atmos/"+ensemble+"/vas/latest/*"))
            ps_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
                 model+"/"+experiment+\
                 "/3hr/atmos/"+ensemble+"/ps/latest/*"))
    elif cmip_ver == 6:

        #Get CMIP6 file paths

        hus_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/6hrLev/hus/gn/latest/*"))
        ta_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/6hrLev/ta/gn/latest/*"))
        ua_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/6hrLev/ua/gn/latest/*"))
        va_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/6hrLev/va/gn/latest/*"))


        huss_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/3hr/huss/gn/latest/*"))
        tas_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/3hr/tas/gn/latest/*"))
        uas_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/3hr/uas/gn/latest/*"))
        vas_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/3hr/vas/gn/latest/*"))
        ps_files = np.sort(glob.glob("/g/data/r87/DRSv3/CMIP6/"+project+"/"+group+"/"+model+\
         "/"+experiment+"/"+ensemble+"/3hr/ps/gn/latest/*"))

    #Isolate the files relevant for the current "year"
    #NOTE will have to change to incorperate months if there is more than one file per year

    hus_fid = get_fid(hus_files, year)
    ta_fid = get_fid(ta_files, year)
    ua_fid = get_fid(ua_files, year)
    va_fid = get_fid(va_files, year)
    huss_fid = get_fid(huss_files, year)
    tas_fid = get_fid(tas_files, year)
    uas_fid = get_fid(uas_files, year)
    vas_fid = get_fid(vas_files, year)
    ps_fid = get_fid(ps_files, year)

    #Load the data
    hus = xr.open_mfdataset([hus_files[i] for i in hus_fid], use_cftime=True)
    ta = xr.open_mfdataset([ta_files[i] for i in ta_fid], use_cftime=True)
    ua = xr.open_mfdataset([ua_files[i] for i in ua_fid], use_cftime=True)
    va = xr.open_mfdataset([va_files[i] for i in va_fid], use_cftime=True)

    #Load surface data and match to 6 hourly
    huss = xr.open_mfdataset([huss_files[i] for i in huss_fid],
                             use_cftime=True)
    tas = xr.open_mfdataset([tas_files[i] for i in tas_fid], use_cftime=True)
    uas = xr.open_mfdataset([uas_files[i] for i in uas_fid], use_cftime=True)
    vas = xr.open_mfdataset([vas_files[i] for i in vas_fid], use_cftime=True)
    ps = xr.open_mfdataset([ps_files[i] for i in ps_fid], use_cftime=True)

    #Trim to the domain given by "domain", as well as the year given by "year". Expand domain
    # for later compairsons with ERA5, and for interpolation of U/V
    domain[0] = domain[0] - 5
    domain[1] = domain[1] + 5
    domain[2] = domain[2] - 5
    domain[3] = domain[3] + 5
    hus = trim_cmip5(hus, domain, year)
    ta = trim_cmip5(ta, domain, year)

    huss = trim_cmip5(huss, domain, year)
    tas = trim_cmip5(tas, domain, year)
    ps = trim_cmip5(ps, domain, year)

    #Interpolate u, v, uas and vas, using a slightly bigger domain, then trim to "domain"
    ua = trim_cmip5(ua, [domain[0], domain[1], domain[2], domain[3]], year)
    va = trim_cmip5(va, [domain[0], domain[1], domain[2], domain[3]], year)
    uas = trim_cmip5(uas, [domain[0], domain[1], domain[2], domain[3]], year)
    vas = trim_cmip5(vas, [domain[0], domain[1], domain[2], domain[3]], year)
    ua = ua.ua.interp({"lon": hus.lon}, method="linear", assume_sorted=True)
    va = va.va.interp({"lat": hus.lat}, method="linear", assume_sorted=True)
    uas = uas.uas.interp({
        "lat": hus.lat,
        "lon": hus.lon
    },
                         method="linear",
                         assume_sorted=True)
    vas = vas.vas.interp({
        "lat": hus.lat,
        "lon": hus.lon
    },
                         method="linear",
                         assume_sorted=True)
    ua = trim_cmip5(ua, domain, year)
    va = trim_cmip5(va, domain, year)
    uas = trim_cmip5(uas, domain, year)
    vas = trim_cmip5(vas, domain, year)

    #Get common times for all datasets
    common_times = np.array(list(set(hus.time.values) & set(ta.time.values) & set(ua.time.values)\
      & set(va.time.values) & set(huss.time.values) & set(tas.time.values)\
      & set(uas.time.values) & set(vas.time.values) & set(ps.time.values)))

    #Restrict all data to common times
    hus = hus.sel({"time": np.in1d(hus.time, common_times)})
    ta = ta.sel({"time": np.in1d(ta.time, common_times)})
    ua = ua.sel({"time": np.in1d(ua.time, common_times)})
    va = va.sel({"time": np.in1d(va.time, common_times)})
    huss = huss.sel({"time": np.in1d(huss.time, common_times)})
    tas = tas.sel({"time": np.in1d(tas.time, common_times)})
    uas = uas.sel({"time": np.in1d(uas.time, common_times)})
    vas = vas.sel({"time": np.in1d(vas.time, common_times)})
    ps = ps.sel({"time": np.in1d(ps.time, common_times)})

    #Either convert vertical coordinate to height or pressure, depending on the model
    names = []
    for name, da in hus.data_vars.items():
        names.append(name)
    if "orog" in names:
        #If the model has been stored on a hybrid height coordinate, it should have the
        #   variable "orog". Convert height coordinate to height ASL, and calculate
        #   pressure via the hydrostatic equation
        z = hus.lev + (hus.b * hus.orog)
        orog = hus.orog.values
        q = hus.hus / (1 - hus.hus)
        tv = ta.ta * ((q + 0.622) / (0.622 * (1 + q)))
        p = np.swapaxes(
            np.swapaxes(ps.ps * np.exp(-9.8 * z / (287 * tv)), 3, 2), 2, 1)
        if ((model
             in ["ACCESS1-3", "ACCESS1-0", "ACCESS-CM2", "ACCESS-ESM1-5"])):
            z = np.swapaxes(z, 0, 1).values
            orog = orog[0]
        else:
            z = np.tile(
                z.values.astype("float32"),
                [ta.ta.shape[0], 1, 1, 1],
            )
    elif np.any(np.in1d(["p0", "ap"], names)):
        #If the model has been stored on a hybrid pressure coordinate, it should have the
        #   variable "p0". Convert hybrid pressure coordinate to pressure, and calculate
        #   height via the hydrostatic equation
        if "p0" in names:
            p = (hus.a * hus.p0 + hus.b * hus.ps).transpose(
                "time", "lev", "lat", "lon")
        elif "ap" in names:
            p = (hus.ap + hus.b * hus.ps).transpose("time", "lev", "lat",
                                                    "lon")
        else:
            raise ValueError(
                "Check the hybrid-pressure coordinate of this model")
        q = hus.hus / (1 - hus.hus)
        tv = ta.ta * ((q + 0.622) / (0.622 * (1 + q)))
        z = (-287 * tv *
             (np.log(p / ps.ps)).transpose("time", "lev", "lat", "lon")) / 9.8
        orog = trim_cmip5( xr.open_dataset(glob.glob("/g/data/r87/DRSv3/CMIP5/"+\
            model+"/historical/fx/atmos/r0i0p0/orog/latest/orog*.nc")[0]).orog,\
            domain, year).values
        orog[orog < 0] = 0
        z = (z + orog).values
    else:
        raise ValueError("Check the vertical coordinate of this model")

    #Sanity checks on pressure and height, one of which is calculated via hydrostatic approx. Note ACCESS-CM2 is
    # missing a temperature level, and so that level will have zero pressure. Ignore sanity check for this model.
    if (z.min() < -1000) | (z.max() > 100000):
        raise ValueError(
            "Potentially erroneous Z values (less than -1000 or greater than 100,000 km"
        )
    if (p.max().values > 200000) | (p.min().values < 0):
        if model != "ACCESS-CM2":
            raise ValueError(
                "Potentially erroneous pressure (less than 0 or greater than 200,000 Pa"
            )

    #Convert quantities into those expected by wrf_(non)_parallel.py
    ta = ta.ta.values - 273.15
    hur = mpcalc.relative_humidity_from_specific_humidity(hus.hus.values, \
         ta*units.units.degC, p.values*units.units.pascal) * 100
    pres = p.values / 100.
    sfc_pres = ps.ps.values / 100.
    tas = tas.tas.values - 273.15
    ta2d = mpcalc.dewpoint_from_specific_humidity(huss.huss.values, tas*units.units.degC, \
         ps.ps.values*units.units.pascal)
    lon = p.lon.values
    lat = p.lat.values

    ua = ua.values
    va = va.values
    uas = uas.values
    vas = vas.values

    #Mask all data above 100 hPa. For ACCESS-CM2, mask data below 20 m
    if model == "ACCESS-CM2":
        ta[(pres < 100) | (p == 0) | (p == np.inf)] = np.nan
        hur[(pres < 100) | (p == 0) | (p == np.inf)] = np.nan
        z[(pres < 100) | (p == 0) | (p == np.inf)] = np.nan
        ua[(pres < 100) | (p == 0) | (p == np.inf)] = np.nan
        va[(pres < 100) | (p == 0) | (p == np.inf)] = np.nan
    else:
        ta[pres < 100] = np.nan
        hur[pres < 100] = np.nan
        z[pres < 100] = np.nan
        ua[pres < 100] = np.nan
        va[pres < 100] = np.nan

    date_list = p.time.values
    date_list = np.array([
        dt.datetime.strptime(date_list[t].strftime(), "%Y-%m-%d %H:%M:%S")
        for t in np.arange(len(date_list))
    ])

    return [ta, hur, z, orog, pres, sfc_pres, ua, va, uas, vas, tas, ta2d, lon,\
         lat, date_list]
Пример #15
0
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)
# =============================================================================
# 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
# =============================================================================
Пример #16
0
def read_cmip6(group, model, experiment, ensemble, year, domain):

    #DEPRECIATED - USE READ_CMIP INSTEAD, SPECIFYING CMIP_VER=6

    #Read CMIP6 data from the r87 project (from oi10 and fs38)

    #For the given model, institute, experiment, get the relevant file paths.
    hus_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/6hrLev/hus/gn/latest/*"))
    ta_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/6hrLev/ta/gn/latest/*"))
    ua_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/6hrLev/ua/gn/latest/*"))
    va_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/6hrLev/va/gn/latest/*"))

    huss_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/3hr/huss/gn/latest/*"))
    tas_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/3hr/tas/gn/latest/*"))
    uas_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/3hr/uas/gn/latest/*"))
    vas_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/3hr/vas/gn/latest/*"))
    ps_files = np.sort(
        glob.glob("/g/data/r87/DRSv3/CMIP6/CMIP/" + group + "/" + model + "/" +
                  experiment + "/" + ensemble + "/3hr/ps/gn/latest/*"))

    #Isolate the files relevant for the current "year"
    #NOTE will have to change to incorperate months if there is more than one file per year

    hus_fid = get_fid(hus_files, year)
    ta_fid = get_fid(ta_files, year)
    ua_fid = get_fid(ua_files, year)
    va_fid = get_fid(va_files, year)
    huss_fid = get_fid(huss_files, year)
    tas_fid = get_fid(tas_files, year)
    uas_fid = get_fid(uas_files, year)
    vas_fid = get_fid(vas_files, year)
    ps_fid = get_fid(ps_files, year)

    #Load the data, match 3 hourly and 6 hourly data
    hus = xr.open_mfdataset([hus_files[i] for i in hus_fid])
    ta = xr.open_mfdataset([ta_files[i] for i in ta_fid])
    ua = xr.open_mfdataset([ua_files[i] for i in ua_fid])
    va = xr.open_mfdataset([va_files[i] for i in va_fid])

    huss = xr.open_mfdataset([huss_files[i] for i in huss_fid])
    huss = huss.sel({"time": np.in1d(huss.time, hus.time)})
    tas = xr.open_mfdataset([tas_files[i] for i in tas_fid])
    tas = tas.sel({"time": np.in1d(tas.time, ta.time)})
    uas = xr.open_mfdataset([uas_files[i] for i in uas_fid])
    uas = uas.sel({"time": np.in1d(uas.time, ua.time)})
    vas = xr.open_mfdataset([vas_files[i] for i in vas_fid])
    vas = vas.sel({"time": np.in1d(vas.time, va.time)})
    ps = xr.open_mfdataset([ps_files[i] for i in ps_fid])
    ps = ps.sel({"time": np.in1d(ps.time, hus.time)})

    #and trim to the domain given by "domain", as well as the year given by "year"
    hus = trim_cmip5(hus, domain, year)
    ta = trim_cmip5(ta, domain, year)

    huss = trim_cmip5(huss, domain, year)
    tas = trim_cmip5(tas, domain, year)
    ps = trim_cmip5(ps, domain, year)

    #Interpolate u, v, uas and vas, using a slightly bigger domain, then trim to "domain"
    ua = trim_cmip5(
        ua, [domain[0] - 5, domain[1] + 5, domain[2] - 5, domain[3] + 5], year)
    va = trim_cmip5(
        va, [domain[0] - 5, domain[1] + 5, domain[2] - 5, domain[3] + 5], year)
    uas = trim_cmip5(
        uas, [domain[0] - 5, domain[1] + 5, domain[2] - 5, domain[3] + 5],
        year)
    vas = trim_cmip5(
        vas, [domain[0] - 5, domain[1] + 5, domain[2] - 5, domain[3] + 5],
        year)
    ua = ua.ua.interp({"lon": hus.lon}, method="linear", assume_sorted=True)
    va = va.va.interp({"lat": hus.lat}, method="linear", assume_sorted=True)
    uas = uas.uas.interp({
        "lat": hus.lat,
        "lon": hus.lon
    },
                         method="linear",
                         assume_sorted=True)
    vas = vas.vas.interp({
        "lat": hus.lat,
        "lon": hus.lon
    },
                         method="linear",
                         assume_sorted=True)
    ua = trim_cmip5(ua, domain, year).values
    va = trim_cmip5(va, domain, year).values
    uas = trim_cmip5(uas, domain, year).values
    vas = trim_cmip5(vas, domain, year).values

    #Convert vertical coordinate to height
    z = hus.lev + (hus.b * hus.orog)
    orog = hus.orog.values

    #Calculate pressure via hydrostatic equation
    q = hus.hus / (1 - hus.hus)
    tv = ta.ta * ((q + 0.622) / (0.622 * (1 + q)))
    p = np.swapaxes(np.swapaxes(ps.ps * np.exp(-9.8 * z / (287 * tv)), 3, 2),
                    2, 1)

    #Convert quantities into those expected by wrf_parallel.py
    ta = ta.ta.values - 273.15
    hur = mpcalc.relative_humidity_from_specific_humidity(hus.hus.values, \
         ta*units.units.degC, p.values*units.units.pascal) * 100
    z = np.tile(z.values, [ta.shape[0], 1, 1, 1])
    pres = p.values / 100.
    sfc_pres = ps.ps.values / 100.
    tas = tas.tas.values - 273.15
    ta2d = mpcalc.dewpoint_from_specific_humidity(hus.hus.values, ta*units.units.degC, \
         p.values*units.units.pascal)
    lon = p.lon.values
    lat = p.lat.values
    date_list = p.time.values

    #Mask all data above 100 hPa
    ta[pres < 100] = np.nan
    hur[pres < 100] = np.nan
    z[pres < 100] = np.nan
    ua[pres < 100] = np.nan
    va[pres < 100] = np.nan

    return [ta, hur, z, orog, pres, sfc_pres, ua, va, uas, vas, tas, ta2d, lon,\
         lat, date_list]
Пример #17
0
    def __init__(self, datea, fhr, atcf, config):
        # Forecast fields to compute

        wnd_lev_1 = [250, 500]
        wnd_lev_2 = [350, 500]
        n_wnd_lev = len(wnd_lev_1)

        # Read steering flow parameters, or use defaults
        steerp1 = float(config['fields'].get('steer_level1', '300'))
        steerp2 = float(config['fields'].get('steer_level2', '850'))
        tcradius = float(config['fields'].get('steer_radius', '333'))

        # lat_lon info
        lat1 = float(config['fields'].get('min_lat', '0.'))
        lat2 = float(config['fields'].get('max_lat', '65.'))
        lon1 = float(config['fields'].get('min_lon', '-180.'))
        lon2 = float(config['fields'].get('max_lon', '-10.'))

        if not 'min_lat' in config:
            config.update({'min_lat': lat1})
            config.update({'max_lat': lat2})
            config.update({'min_lon': lon1})
            config.update({'max_lon': lon2})

        self.fhr = fhr
        self.atcf_files = atcf.atcf_files
        self.config = config
        self.nens = int(len(self.atcf_files))
        df_files = {}
        self.datea_str = datea
        self.datea = dt.datetime.strptime(datea, '%Y%m%d%H')
        self.datea_s = self.datea.strftime("%m%d%H%M")
        self.fff = str(self.fhr + 1000)[1:]
        datea_1 = self.datea + dt.timedelta(hours=self.fhr)
        datea_1 = datea_1.strftime("%m%d%H%M")

        self.dpp = importlib.import_module(config['io_module'])

        logging.warning("Computing hour {0} ensemble fields".format(self.fff))

        #  Obtain the ensemble lat/lon information, replace missing values with mean
        self.ens_lat, self.ens_lon = atcf.ens_lat_lon_time(self.fhr)

        e_cnt = 0
        m_lat = 0.0
        m_lon = 0.0
        for n in range(self.nens):
            if self.ens_lat[n] != atcf.missing and self.ens_lon[
                    n] != atcf.missing:
                e_cnt = e_cnt + 1
                m_lat = m_lat + self.ens_lat[n]
                m_lon = m_lon + self.ens_lon[n]

        if e_cnt > 0:
            m_lon = m_lon / e_cnt
            m_lat = m_lat / e_cnt

            for n in range(self.nens):
                if self.ens_lat[n] == atcf.missing or self.ens_lon[
                        n] == atcf.missing:
                    self.ens_lat[n] = m_lat
                    self.ens_lon[n] = m_lon

        #  Read grib file information for this forecast hour
        g1 = self.dpp.ReadGribFiles(self.datea_str, self.fhr, self.config)

        dencode = {
            'ensemble_data': {
                'dtype': 'float32'
            },
            'latitude': {
                'dtype': 'float32'
            },
            'longitude': {
                'dtype': 'float32'
            },
            'ensemble': {
                'dtype': 'int32'
            }
        }

        #  Compute steering wind components
        uoutfile = '{0}/{1}_f{2}_usteer_ens.nc'.format(config['work_dir'],
                                                       str(self.datea_str),
                                                       self.fff)
        voutfile = '{0}/{1}_f{2}_vsteer_ens.nc'.format(config['work_dir'],
                                                       str(self.datea_str),
                                                       self.fff)
        if (not os.path.isfile(uoutfile)
                or not os.path.isfile(voutfile)) and config['fields'].get(
                    'calc_uvsteer', 'True') == 'True':

            logging.warning("  Computing steering wind information")

            inpDict = {'isobaricInhPa': (steerp1, steerp2)}
            inpDict = g1.set_var_bounds('zonal_wind', inpDict)

            #  Create output arrays
            outDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': 'zonal steering wind',
                'units': 'm/s',
                '_FillValue': -9999.
            }
            outDict = g1.set_var_bounds('zonal_wind', outDict)
            uensmat = g1.create_ens_array('zonal_wind', self.nens, outDict)

            outDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': 'meridional steering wind',
                'units': 'm/s',
                '_FillValue': -9999.
            }
            outDict = g1.set_var_bounds('meridional_wind', outDict)
            vensmat = g1.create_ens_array('meridional_wind', self.nens,
                                          outDict)

            outDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': 'steering wind vorticity',
                'units': '1/s',
                '_FillValue': -9999.
            }
            outDict = g1.set_var_bounds('zonal_wind', outDict)
            vortmat = g1.create_ens_array('zonal_wind', self.nens, outDict)

            wencode = {
                'latitude': {
                    'dtype': 'float32'
                },
                'longitude': {
                    'dtype': 'float32'
                }
            }

            for n in range(self.nens):

                #  Read global zonal and meridional wind, write to file
                uwnd = g1.read_grib_field('zonal_wind', n, inpDict).rename('u')
                vwnd = g1.read_grib_field('meridional_wind', n,
                                          inpDict).rename('v')

                #             print(uwnd[:,0,0])
                #             print(vwnd[:,0,0])
                #             sys.exit(2)

                uwnd.to_netcdf('wind_info.nc',
                               mode='w',
                               encoding=wencode,
                               format='NETCDF3_CLASSIC')
                vwnd.to_netcdf('wind_info.nc',
                               mode='a',
                               encoding=wencode,
                               format='NETCDF3_CLASSIC')

                latvec = uwnd.latitude.values
                lonvec = uwnd.longitude.values

                if e_cnt > 0:

                    latcen = latvec[np.abs(latvec - self.ens_lat[n]).argmin()]
                    loncen = lonvec[np.abs(lonvec - self.ens_lon[n]).argmin()]

                    #  Call NCL to remove TC winds, read result from file
                    os.system('ncl -Q {0}/tc_steer.ncl tclat={1} tclon={2} tcradius={3}'.format(config['script_dir'],\
                                          str(latcen), str(loncen), str(tcradius)))

                    wfile = nc.Dataset('wind_info.nc')
                    uwnd[:, :, :] = wfile.variables['u'][:, :, :]
                    vwnd[:, :, :] = wfile.variables['v'][:, :, :]

                    os.remove('wind_info.nc')

                #  Integrate the winds over the layer to obtain the steering wind
                pres, lat, lon = uwnd.indexes.values()
                nlev = len(pres)

                uint = uwnd[0, :, :]
                uint[:, :] = 0.0
                vint = vwnd[0, :, :]
                vint[:, :] = 0.0

                for k in range(nlev - 1):

                    uint[:, :] = uint[:, :] + 0.5 * (uwnd[k, :, :] + uwnd[
                        k + 1, :, :]) * abs(pres[k + 1] - pres[k])
                    vint[:, :] = vint[:, :] + 0.5 * (vwnd[k, :, :] + vwnd[
                        k + 1, :, :]) * abs(pres[k + 1] - pres[k])

#             if pres[0] > pres[-1]:
#               uint = -np.trapz(uwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])
#               vint = -np.trapz(vwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])
#             else:
#               uint = np.trapz(uwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])
#               vint = np.trapz(vwnd[:,:,:], pres, axis=0) / abs(pres[-1]-pres[0])

                if lat[0] > lat[-1]:
                    slat1 = lat2
                    slat2 = lat1
                else:
                    slat1 = lat1
                    slat2 = lat2

                #  Write steering flow to ensemble arrays
                uensmat[n, :, :] = np.squeeze(
                    uint.sel(latitude=slice(slat1, slat2),
                             longitude=slice(lon1,
                                             lon2))) / abs(pres[-1] - pres[0])
                vensmat[n, :, :] = np.squeeze(
                    vint.sel(latitude=slice(slat1, slat2),
                             longitude=slice(lon1,
                                             lon2))) / abs(pres[-1] - pres[0])

                #  Compute the vorticity associated with the steering wind

#             circ = VectorWind(unew, vnew).vorticity() * 1.0e5

#             vortmat[n,:,:] = np.squeeze(circ.sel(latitude=slice(lat2, lat1), longitude=slice(lon1, lon2)))

            uensmat.to_netcdf(uoutfile, encoding=dencode)
            vensmat.to_netcdf(voutfile, encoding=dencode)


#          vortmat.to_netcdf(vortfile, encoding=dencode)

        else:

            logging.warning("  Obtaining steering wind information from file")

        #  Read geopotential height from file, if ensemble file is not present
        if config['fields'].get('calc_height', 'True') == 'True':

            if 'height_levels' in config['fields']:
                height_list = json.loads(config['fields'].get('height_levels'))
            else:
                height_list = [500]

            for level in height_list:

                levstr = '%0.3i' % int(level)
                outfile = '{0}/{1}_f{2}_h{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)

                if not os.path.isfile(outfile):

                    logging.warning(
                        '  Computing {0} hPa height'.format(levstr))

                    vDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description': '{0} hPa height'.format(levstr),
                        'units': 'm',
                        '_FillValue': -9999.
                    }
                    vDict = g1.set_var_bounds('geopotential_height', vDict)
                    ensmat = g1.create_ens_array('geopotential_height',
                                                 g1.nens, vDict)

                    for n in range(g1.nens):
                        ensmat[n, :, :] = np.squeeze(
                            g1.read_grib_field('geopotential_height', n,
                                               vDict))

                    ensmat.to_netcdf(outfile, encoding=dencode)

                elif os.path.isfile(outfile):

                    logging.warning(
                        "  Obtaining {0} hPa height data from {1}".format(
                            levstr, outfile))

        #  Compute 250 hPa PV if the file does not exist
        outfile = '{0}/{1}_f{2}_pv250_ens.nc'.format(config['work_dir'],
                                                     str(self.datea_str),
                                                     self.fff)
        if (not os.path.isfile(outfile)
                and config['fields'].get('calc_pv250hPa', 'True') == 'True'):

            logging.warning("  Computing 250 hPa PV")

            vDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'isobaricInhPa': (200, 300),
                'description': '250 hPa Potential Vorticity',
                'units': 'PVU',
                '_FillValue': -9999.
            }
            vDict = g1.set_var_bounds('zonal_wind', vDict)

            ensmat = g1.create_ens_array('zonal_wind', self.nens, vDict)

            for n in range(self.nens):

                #  Read all the necessary files from file, smooth fields, so sensitivities are useful
                tmpk = g1.read_grib_field('temperature', n, vDict) * units('K')

                lats = tmpk.latitude.values * units('degrees')
                lons = tmpk.longitude.values * units('degrees')
                pres = tmpk.isobaricInhPa.values * units('hPa')

                tmpk = mpcalc.smooth_n_point(tmpk, 9, 4)

                thta = mpcalc.potential_temperature(pres[:, None, None], tmpk)

                uwnd = mpcalc.smooth_n_point(
                    g1.read_grib_field('zonal_wind', n, vDict) * units('m/s'),
                    9, 4)
                vwnd = mpcalc.smooth_n_point(
                    g1.read_grib_field('meridional_wind', n, vDict) *
                    units('m/s'), 9, 4)

                dx, dy = mpcalc.lat_lon_grid_deltas(lons,
                                                    lats,
                                                    x_dim=-1,
                                                    y_dim=-2,
                                                    geod=None)

                #  Compute PV and place in ensemble array
                pvout = mpcalc.potential_vorticity_baroclinic(
                    thta, pres[:, None, None], uwnd, vwnd, dx[None, :, :],
                    dy[None, :, :], lats[None, :, None])

                ensmat[n, :, :] = np.squeeze(pvout[np.where(
                    pres == 250 * units('hPa'))[0], :, :]) * 1.0e6

            ensmat.to_netcdf(outfile, encoding=dencode)

        elif os.path.isfile(outfile):

            logging.warning(
                "  Obtaining 250 hPa PV data from {0}".format(outfile))

        #  Compute the equivalent potential temperature (if desired and file is missing)
        if config['fields'].get('calc_theta-e', 'False') == 'True':

            if 'theta-e_levels' in config['fields']:
                thetae_list = json.loads(
                    config['fields'].get('theta-e_levels'))
            else:
                thetae_list = [700, 850]

            for level in thetae_list:

                levstr = '%0.3i' % int(level)
                outfile = '{0}/{1}_f{2}_e{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)

                if not os.path.isfile(outfile):

                    logging.warning(
                        '  Computing {0} hPa Theta-E'.format(levstr))

                    vDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description':
                        '{0} hPa Equivalent Potential Temperature'.format(
                            levstr),
                        'units':
                        'K',
                        '_FillValue':
                        -9999.
                    }
                    vDict = g1.set_var_bounds('temperature', vDict)

                    ensmat = g1.create_ens_array('temperature', g1.nens, vDict)

                    for n in range(g1.nens):

                        tmpk = g1.read_grib_field('temperature', n,
                                                  vDict) * units.K
                        pres = tmpk.isobaricInhPa.values * units.hPa

                        if g1.has_specific_humidity:
                            qvap = np.squeeze(
                                g1.read_grib_field('specific_humidity', n,
                                                   vDict))
                            tdew = mpcalc.dewpoint_from_specific_humidity(
                                pres[None, None], tmpk, qvap)
                        else:
                            relh = g1.read_grib_field('relative_humidity', n,
                                                      vDict)
                            relh = np.minimum(np.maximum(relh, 0.01),
                                              100.0) * units.percent
                            tdew = mpcalc.dewpoint_from_relative_humidity(
                                tmpk, relh)

                        ensmat[n, :, :] = np.squeeze(
                            mpcalc.equivalent_potential_temperature(
                                pres[None, None], tmpk, tdew))

                    ensmat.to_netcdf(outfile, encoding=dencode)

                elif os.path.isfile(outfile):

                    logging.warning(
                        "  Obtaining {0} hPa Theta-e data from {1}".format(
                            levstr, outfile))

        #  Compute the 500-850 hPa water vapor mixing ratio (if desired and file is missing)
        outfile = '{0}/{1}_f{2}_q500-850hPa_ens.nc'.format(
            config['work_dir'], str(self.datea_str), self.fff)
        if (not os.path.isfile(outfile) and config['fields'].get(
                'calc_q500-850hPa', 'False') == 'True'):

            logging.warning("  Computing 500-850 hPa Water Vapor")

            vDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'description': '500-850 hPa Integrated Water Vapor',
                'units': 'hPa',
                '_FillValue': -9999.
            }
            vDict = g1.set_var_bounds('temperature', vDict)

            ensmat = g1.create_ens_array('temperature', len(self.atcf_files),
                                         vDict)

            vDict = {
                'latitude': (lat1, lat2),
                'longitude': (lon1, lon2),
                'isobaricInhPa': (500, 850),
                'description': '500-850 hPa Integrated Water Vapor',
                'units': 'hPa',
                '_FillValue': -9999.
            }
            vDict = g1.set_var_bounds('temperature', vDict)

            for n in range(self.nens):

                tmpk = np.squeeze(g1.read_grib_field('temperature', n,
                                                     vDict)) * units('K')
                pres = (tmpk.isobaricInhPa.values * units.hPa).to(units.Pa)

                if g1.has_specific_humidity:
                    qvap = mpcalc.mixing_ratio_from_specific_humidity(
                        g1.read_grib_field('specific_humidity', n, vDict))
                else:
                    relh = np.minimum(
                        np.maximum(
                            g1.read_grib_field('relative_humidity', n, vDict),
                            0.01), 100.0) * units('percent')
                    qvap = mpcalc.mixing_ratio_from_relative_humidity(
                        pres[:, None, None], tmpk, relh)

                #  Integrate water vapor over the pressure levels
                ensmat[n, :, :] = np.abs(np.trapz(
                    qvap, pres, axis=0)) / mpcon.earth_gravity

            ensmat.to_netcdf(outfile, encoding=dencode)

        elif os.path.isfile(outfile):

            logging.warning(
                "  Obtaining 500-850 hPa water vapor data from {0}".format(
                    outfile))

        #  Compute wind-related forecast fields (if desired and file is missing)
        if config['fields'].get('calc_winds', 'False') == 'True':

            if 'wind_levels' in config['fields']:
                wind_list = json.loads(config['fields'].get('wind_levels'))
            else:
                wind_list = [850]

            for level in wind_list:

                levstr = '%0.3i' % int(level)
                ufile = '{0}/{1}_f{2}_u{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)
                vfile = '{0}/{1}_f{2}_v{3}hPa_ens.nc'.format(
                    config['work_dir'], str(self.datea_str), self.fff, levstr)

                if (not os.path.isfile(ufile)) or (not os.path.isfile(vfile)):

                    logging.warning(
                        '  Computing {0} hPa wind information'.format(levstr))

                    uDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description': '{0} hPa zonal wind'.format(levstr),
                        'units': 'm/s',
                        '_FillValue': -9999.
                    }
                    uDict = g1.set_var_bounds('zonal_wind', uDict)

                    uensmat = g1.create_ens_array('zonal_wind', g1.nens, uDict)

                    vDict = {
                        'latitude': (lat1, lat2),
                        'longitude': (lon1, lon2),
                        'isobaricInhPa': (level, level),
                        'description':
                        '{0} hPa meridional wind'.format(levstr),
                        'units': 'm/s',
                        '_FillValue': -9999.
                    }
                    vDict = g1.set_var_bounds('meridional_wind', vDict)

                    vensmat = g1.create_ens_array('meridional_wind', g1.nens,
                                                  vDict)

                    for n in range(g1.nens):

                        uwnd = g1.read_grib_field('zonal_wind', n,
                                                  uDict).squeeze()
                        vwnd = g1.read_grib_field('meridional_wind', n,
                                                  vDict).squeeze()

                        uensmat[n, :, :] = uwnd[:, :]
                        vensmat[n, :, :] = vwnd[:, :]

                    uensmat.to_netcdf(ufile, encoding=dencode)
                    vensmat.to_netcdf(vfile, encoding=dencode)

                elif os.path.isfile(outfile):

                    logging.warning(
                        "  Obtaining {0} hPa wind information from file".
                        format(levstr))