Ejemplo n.º 1
0
def run_calcs(df, ctx):
    """Do our maths."""
    # Convert sea level pressure to station pressure
    df["pressure"] = mcalc.add_height_to_pressure(
        df["slp"].values * units("millibars"),
        ctx["_nt"].sts[ctx["station"]]["elevation"] * units("m"),
    ).to(units("millibar"))
    # Compute the mixing ratio
    df["mixingratio"] = mcalc.mixing_ratio_from_relative_humidity(
        df["relh"].values * units("percent"),
        df["tmpf"].values * units("degF"),
        df["pressure"].values * units("millibars"),
    )
    # Compute the saturation mixing ratio
    df["saturation_mixingratio"] = mcalc.saturation_mixing_ratio(
        df["pressure"].values * units("millibars"),
        df["tmpf"].values * units("degF"),
    )
    df["vapor_pressure"] = mcalc.vapor_pressure(
        df["pressure"].values * units("millibars"),
        df["mixingratio"].values * units("kg/kg"),
    ).to(units("kPa"))
    df["saturation_vapor_pressure"] = mcalc.vapor_pressure(
        df["pressure"].values * units("millibars"),
        df["saturation_mixingratio"].values * units("kg/kg"),
    ).to(units("kPa"))
    df["vpd"] = df["saturation_vapor_pressure"] - df["vapor_pressure"]
    # remove any NaN rows
    df = df.dropna()
    group = df.groupby("year")
    df = group.aggregate(np.average)

    df["dwpf"] = (mcalc.dewpoint(df["vapor_pressure"].values *
                                 units("kPa")).to(units("degF")).m)
    return df
Ejemplo n.º 2
0
def main():
    """Go Main Go"""
    pgconn = get_dbconn('scan')
    for station in ['S2004', 'S2196', 'S2002', 'S2072', 'S2068',
                    'S2031', 'S2001', 'S2047']:
        df = read_sql("""
        select extract(year from valid + '2 months'::interval) as wy,
        tmpf, dwpf from alldata where station = %s and tmpf is not null
        and dwpf is not null
        """, pgconn, params=(station, ), index_col=None)
        df['mixingratio'] = meteorology.mixing_ratio(
            temperature(df['dwpf'].values, 'F')).value('KG/KG')
        df['vapor_pressure'] = mcalc.vapor_pressure(
            1000. * units.mbar,
            df['mixingratio'].values * units('kg/kg')).to(units('kPa'))
        df['saturation_mixingratio'] = (
            meteorology.mixing_ratio(
                temperature(df['tmpf'].values, 'F')).value('KG/KG'))
        df['saturation_vapor_pressure'] = mcalc.vapor_pressure(
            1000. * units.mbar,
            df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa'))
        df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure']
        means = df.groupby('wy').mean()
        counts = df.groupby('wy').count()
        for yr, row in means.iterrows():
            print(("%s,%s,%.0f,%.3f"
                   ) % (yr, station, counts.at[yr, 'vpd'], row['vpd']))
Ejemplo n.º 3
0
def run_calcs(df, ctx):
    """Do our maths."""
    # Convert sea level pressure to station pressure
    df['pressure'] = mcalc.add_height_to_pressure(
        df['slp'].values * units('millibars'),
        ctx['nt'].sts[ctx['station']]['elevation'] * units('m')).to(
            units('millibar'))
    # Compute the mixing ratio
    df['mixingratio'] = mcalc.mixing_ratio_from_relative_humidity(
        df['relh'].values * units('percent'),
        df['tmpf'].values * units('degF'),
        df['pressure'].values * units('millibars'))
    # Compute the saturation mixing ratio
    df['saturation_mixingratio'] = mcalc.saturation_mixing_ratio(
        df['pressure'].values * units('millibars'),
        df['tmpf'].values * units('degF'))
    df['vapor_pressure'] = mcalc.vapor_pressure(
        df['pressure'].values * units('millibars'),
        df['mixingratio'].values * units('kg/kg')).to(units('kPa'))
    df['saturation_vapor_pressure'] = mcalc.vapor_pressure(
        df['pressure'].values * units('millibars'),
        df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa'))
    df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure']
    group = df.groupby('year')
    df = group.aggregate(np.average)

    df['dwpf'] = mcalc.dewpoint(df['vapor_pressure'].values * units('kPa')).to(
        units('degF')).m
    return df
Ejemplo n.º 4
0
def add_entropy(ax,
                pressure,
                temperature,
                mixing_ratio,
                ds=100,
                linewidth=1.0):
    "add entropy curves and rescale values to fit in by 0.5*entropy + ds"
    p = pressure * units('mbar')
    T = temperature * units('degC')
    q = mixing_ratio * units('kilogram/kilogram')
    qs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T), p)
    Td = mpcalc.dewpoint(mpcalc.vapor_pressure(p, q))  # dewpoint
    Tp = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')  # parcel profile

    # specific entropy [joule/(kg*K)]
    # sd : specific entropy of dry air
    # sm1 : specific entropy of airborne mositure in state 1 (water vapor)
    # sm2 : specific entropy of airborne mositure in state 2 (saturated water vapor)

    sd = entropy(T, q * 0, p)
    sm1 = entropy(T, q, p)
    sm2 = entropy(T, qs, p)

    ax.plot(sd.magnitude * 0.5 + ds, p, '--k')
    ax.plot(sm1.magnitude * 0.5 + ds, p, '--b')
    ax.plot(sm2.magnitude * 0.5 + ds, p, '--r')
Ejemplo n.º 5
0
def plot(variables, prev_vars, pltenv):

    cont_int = 10
    cont_smooth = 0.5

    x = pltenv['x']
    y = pltenv['y']
    m = pltenv['map']

    bbox = dict(boxstyle="square", ec='None', fc=(1, 1, 1, 0.75))

    #var = (variables['T2'][0]-273.15) * 1.8 + 32
    var = variables['Q2'][0] * 1000.
    varp = variables['AFWA_MSLP'][0] * 0.01
    var = var * units('g/kg')
    vare = mcalc.vapor_pressure(varp * units.mbar, var)
    vartd = mcalc.dewpoint(vare)
    vartd = vartd.to('degF')
    var2 = ndimage.gaussian_filter(vartd, sigma=cont_smooth)
    levels = np.arange(-100, 150, cont_int)
    levels2 = np.arange(-40, 140, 1)

    P = m.contour(x, y, var2, levels=levels, colors='k')
    plt.clabel(P, inline=1, fontsize=10, fmt='%1.0f', inline_spacing=1)

    P = m.contour(x, y, var2, levels=[32], colors='r')
    plt.clabel(P, inline=1, fontsize=10, fmt='%1.0f', inline_spacing=1)

    m.contourf(x, y, vartd, cmap='gist_ncar', levels=levels2, extend='both')
Ejemplo n.º 6
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)
Ejemplo n.º 7
0
def mixingratio_to_relativehumidity(pressure, temperature, mixing_ratio):
    actual_vapour_pressure = mpcalc.vapor_pressure(
        pressure * units['hPa'], mixing_ratio * units['g/kg']).to_base_units()
    sat_vapour_pressure = mpcalc.saturation_vapor_pressure(
        temperature * units['degC']).to_base_units()
    rh = actual_vapour_pressure / sat_vapour_pressure
    return rh
Ejemplo n.º 8
0
def convert_H2O_MR_to_Td(H2O_MR, p):
    # input water vapour mass mixing ration in (mWV / mDA) kg/kg

    WVMR = H2O_MR * 1000  # convert to grams
    WVMR = WVMR * units('g/kg')
    e_1 = mpcalc.vapor_pressure(p_NUCAPS_orig, WVMR)
    T_d = mpcalc.dewpoint(e_1)
    return T_d
Ejemplo n.º 9
0
def add_curves(ax,
               pressure,
               temperature,
               mixing_ratio,
               altitude,
               linewidth=1.0,
               LH_Tdepend=False):
    """
    overlaying new curves of multiple soundings from profiles
    """
    p = pressure * units('mbar')
    T = temperature * units('degC')
    q = mixing_ratio * units('kilogram/kilogram')
    qs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T), p)
    Td = mpcalc.dewpoint(mpcalc.vapor_pressure(p, q))  # dewpoint
    Tp = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')  # parcel profile

    # Altitude based on the hydrostatic eq.
    if len(altitude) == len(pressure):  # (1) altitudes for whole levels
        altitude = altitude * units('meter')
    elif len(altitude
             ) == 1:  # (2) known altitude where the soundings was launched
        z_surf = altitude.copy() * units('meter')
        # given altitude
        altitude = np.zeros((np.size(T))) * units('meter')
        for i in range(np.size(T)):
            altitude[i] = mpcalc.thickness_hydrostatic(
                p[:i + 1], T[:i + 1]) + z_surf  # Hypsometric Eq. for height
    else:
        print(
            '***NOTE***: the altitude at the surface is assumed 0 meter, and altitudes are derived based on the hypsometric equation'
        )
        altitude = np.zeros(
            (np.size(T))) * units('meter')  # surface is 0 meter
        for i in range(np.size(T)):
            altitude[i] = mpcalc.thickness_hydrostatic(
                p[:i + 1], T[:i + 1])  # Hypsometric Eq. for height

    # specific energies
    if LH_Tdepend == False:
        mse = mpcalc.moist_static_energy(altitude, T, q)
        mse_s = mpcalc.moist_static_energy(altitude, T, qs)
        dse = mpcalc.dry_static_energy(altitude, T)
    else:
        # A short course in cloud physics, Roger and Yau (1989)
        Lvt = (2500.8 - 2.36 * T.magnitude +
               0.0016 * T.magnitude**2 - 0.00006 * T.magnitude**3) * units(
                   'joule/gram')  # latent heat of evaporation
        #Lf = 2834.1 - 0.29*T - 0.004*T**2                  # latent heat of fusion

        mse = Cp_d * T + g * altitude + Lvt * q
        mse_s = Cp_d * T + g * altitude + Lvt * qs
        dse = mpcalc.dry_static_energy(altitude, T)

    ax.plot(dse, p, '--k', linewidth=linewidth)
    ax.plot(mse, p, '--b', linewidth=linewidth)
    ax.plot(mse_s, p, '--r', linewidth=linewidth)
Ejemplo n.º 10
0
def down_cape(p_start=None):

    if p_start not in ls.lev:
        raise ValueError(
            "Please provide pressure of one level of large-scale dataset to start calculating DCAPE from."
        )

    # find index of p_start
    start_level = int((abs(ls.lev - p_start)).argmin())

    # get temperature and humidity from large-scale state
    temp = ls.T.sel(lev=slice(None, 990)).metpy.unit_array
    mix = ls.r.sel(lev=slice(None, 990)).metpy.unit_array.to('kg/kg')
    p_vector = ls.lev.sel(lev=slice(None, 990)).metpy.unit_array

    # get dew-point temperature
    vap_pres = mpcalc.vapor_pressure(p_vector, mix)
    dew_temp = mpcalc.dewpoint(vap_pres)

    # pressure levels to integrate over
    p_down = ls.lev.sel(lev=slice(p_start, 990))

    # find NaNs
    l_valid = ls.T[:, start_level].notnull().values

    d_cape = xr.full_like(ls.cape, np.nan)
    x = p_down.values
    temp = temp[l_valid, :]
    dew_temp = dew_temp[l_valid, :]
    # loop over all non-NaN times in large-scale state
    for i, this_time in enumerate(ls.T[l_valid].time):
        print(i)
        # bug: p_start has to be multiplied with units when given as argument, not beforehand
        wb_temp = mpcalc.wet_bulb_temperature(p_start * units['hPa'],
                                              temp[i, start_level],
                                              dew_temp[i, start_level])

        # create placeholder for moist adiabat temperature
        moist_adiabat = temp[i, start_level:].to('degC')

        moist_adiabat_below = mpcalc.moist_lapse(p_vector[start_level + 1:],
                                                 wb_temp,
                                                 p_start * units['hPa'])
        moist_adiabat[0] = wb_temp
        moist_adiabat[1:] = moist_adiabat_below

        env_temp = temp[i, start_level:]
        temp_diff = moist_adiabat - env_temp

        y = temp_diff.magnitude
        d_cape.loc[this_time] = (mpconsts.Rd *
                                 (np.trapz(y, np.log(x)) * units.degK)).to(
                                     units('J/kg'))

    d_cape.attrs['long_name'] = 'Downward CAPE'
    return xr.merge([ls, xr.Dataset({'d_cape': d_cape})])
Ejemplo n.º 11
0
def run_calcs(df):
    """Do our maths"""
    df['mixingratio'] = meteorology.mixing_ratio(
        temperature(df['dwpf'].values, 'F')).value('KG/KG')
    df['vapor_pressure'] = mcalc.vapor_pressure(
        1000. * units.mbar,
        df['mixingratio'].values * units('kg/kg')).to(units('kPa'))
    df['saturation_mixingratio'] = (meteorology.mixing_ratio(
        temperature(df['tmpf'].values, 'F')).value('KG/KG'))
    df['saturation_vapor_pressure'] = mcalc.vapor_pressure(
        1000. * units.mbar,
        df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa'))
    df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure']
    group = df.groupby('year')
    df = group.aggregate(np.average)

    df['dwpf'] = meteorology.dewpoint_from_pq(
        pressure(1000, 'MB'), mixingratio(df['mixingratio'].values,
                                          'KG/KG')).value('F')
    return df
Ejemplo n.º 12
0
    def plot(T, p, r, f_in, dir_out):
        T = T * units.K
        p = p * units.millibar

        vp = mpcalc.vapor_pressure(p, r)
        svp = mpcalc.saturation_vapor_pressure(T)
        Td = mpcalc.dewpoint_from_relative_humidity(T, vp / svp)
        Td[np.isnan(
            Td)] = -99. * units.degree_Celsius  # fill nan with very low temp

        f_in_basename = os.path.basename(f_in)
        prof.core(p,
                  T,
                  Td,
                  u,
                  v,
                  saveto=dir_out + 'prof_' + f_in_basename + '.png',
                  title=f_in_basename)
Ejemplo n.º 13
0
def plot_profile(f, fig, skew):

    ds = xr.open_dataset(f)
    ds = ds.isel(Time=0)

    Theta_m = ds.T.mean(areadims) + basetemp
    pm = (ds.P + ds.PB).mean(areadims)
    Qvm = (ds.QVAPOR).mean(areadims)

    U = wrf.destagger(ds.U, 2, meta=True)
    V = wrf.destagger(ds.V, 1, meta=True)

    um = U.mean(areadims)
    vm = V.mean(areadims)

    Tm = Theta_m * (pm / 1e5)**(2 / 7)

    p = pm.values / 100. * units.millibar
    Tm = Tm.values * units.K
    Qv = Qvm.values

    vp = mpcalc.vapor_pressure(p, Qv)
    svp = mpcalc.saturation_vapor_pressure(Tm)
    #svp[svp<1e-16*units.millibar] = 1e-16 * units.millibar

    Td = mpcalc.dewpoint_from_relative_humidity(Tm, vp / svp)
    Td[np.isnan(
        Td)] = -99. * units.degree_Celsius  # fill nan with very low temp
    # print('Dewpoints: ', Td)
    # print('Temperatures: ', Tm)

    u = um.values
    v = vm.values

    skew.plot(p, Tm, 'r.-', ms=1, lw=.5, label='mean T')
    skew.plot(p, Td, 'g.-', ms=5, lw=2, label='mean Td')
    #skew.plot_barbs(p, u, v)
    return Tm, Td, p
Ejemplo n.º 14
0
def plotter(fdict):
    """ Go """
    pgconn = get_dbconn("asos")
    ctx = get_autoplot_context(fdict, get_description())
    station = ctx["zstation"]
    year = ctx["year"]
    varname = ctx["var"]

    df = read_sql(
        """
        SELECT extract(year from valid) as year,
        coalesce(mslp, alti * 33.8639, 1013.25) as slp,
        extract(doy from valid) as doy, tmpf, dwpf, relh from alldata
        where station = %s and dwpf > -50 and dwpf < 90 and
        tmpf > -50 and tmpf < 120 and valid > '1950-01-01'
        and report_type = 2
    """,
        pgconn,
        params=(station, ),
        index_col=None,
    )
    if df.empty:
        raise NoDataFound("No Data was found.")
    # saturation vapor pressure
    # Convert sea level pressure to station pressure
    df["pressure"] = mcalc.add_height_to_pressure(
        df["slp"].values * units("millibars"),
        ctx["_nt"].sts[station]["elevation"] * units("m"),
    ).to(units("millibar"))
    # Compute the mixing ratio
    df["mixing_ratio"] = mcalc.mixing_ratio_from_relative_humidity(
        df["relh"].values * units("percent"),
        df["tmpf"].values * units("degF"),
        df["pressure"].values * units("millibars"),
    )
    # Compute the saturation mixing ratio
    df["saturation_mixingratio"] = mcalc.saturation_mixing_ratio(
        df["pressure"].values * units("millibars"),
        df["tmpf"].values * units("degF"),
    )
    df["vapor_pressure"] = mcalc.vapor_pressure(
        df["pressure"].values * units("millibars"),
        df["mixing_ratio"].values * units("kg/kg"),
    ).to(units("kPa"))
    df["saturation_vapor_pressure"] = mcalc.vapor_pressure(
        df["pressure"].values * units("millibars"),
        df["saturation_mixingratio"].values * units("kg/kg"),
    ).to(units("kPa"))
    df["vpd"] = df["saturation_vapor_pressure"] - df["vapor_pressure"]

    dailymeans = df[["year", "doy", varname]].groupby(["year", "doy"]).mean()
    dailymeans = dailymeans.reset_index()

    df2 = dailymeans[["doy", varname]].groupby("doy").describe()

    dyear = df[df["year"] == year]
    df3 = dyear[["doy", varname]].groupby("doy").describe()
    df3[(varname, "diff")] = df3[(varname, "mean")] - df2[(varname, "mean")]

    (fig, ax) = plt.subplots(2, 1, figsize=(8, 6))
    multiplier = 1000.0 if varname == "mixing_ratio" else 10.0

    ax[0].fill_between(
        df2[(varname, "min")].index.values,
        df2[(varname, "min")].values * multiplier,
        df2[(varname, "max")].values * multiplier,
        color="gray",
    )

    ax[0].plot(
        df2[(varname, "mean")].index.values,
        df2[(varname, "mean")].values * multiplier,
        label="Climatology",
    )
    ax[0].plot(
        df3[(varname, "mean")].index.values,
        df3[(varname, "mean")].values * multiplier,
        color="r",
        label="%s" % (year, ),
    )

    ax[0].set_title(("%s [%s]\nDaily Mean Surface %s") %
                    (station, ctx["_nt"].sts[station]["name"], PDICT[varname]))
    lbl = ("Mixing Ratio ($g/kg$)"
           if varname == "mixing_ratio" else PDICT[varname])
    ax[0].set_ylabel(lbl)
    ax[0].set_xlim(0, 366)
    ax[0].set_ylim(bottom=0)
    ax[0].set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335))
    ax[0].set_xticklabels(calendar.month_abbr[1:])
    ax[0].grid(True)
    ax[0].legend(loc=2, fontsize=10)

    cabove = "b" if varname == "mixing_ratio" else "r"
    cbelow = "r" if cabove == "b" else "b"
    rects = ax[1].bar(
        df3[(varname, "diff")].index.values,
        df3[(varname, "diff")].values * multiplier,
        facecolor=cabove,
        edgecolor=cabove,
    )
    for rect in rects:
        if rect.get_height() < 0.0:
            rect.set_facecolor(cbelow)
            rect.set_edgecolor(cbelow)

    plunits = "$g/kg$" if varname == "mixing_ratio" else "hPa"
    ax[1].set_ylabel("%.0f Departure (%s)" % (year, plunits))
    ax[1].set_xlim(0, 366)
    ax[1].set_xticks((1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335))
    ax[1].set_xticklabels(calendar.month_abbr[1:])
    ax[1].grid(True)
    return fig, df3
Ejemplo n.º 15
0
e = 6.112 * np.exp((17.67 * T) / (T + 243.5)) * (RH / 100)
r = 0.622 * (e) / (p - e) * 1000.
# e = mpcalc.vapor_pressure(1000. * units.mbar, mixing)

df = pd.DataFrame({
    'pressure': p,
    'temperature': T,
    'r': r,
    'speed': ws,
    'direction': wd
})

p = df['pressure'].values * units.hPa
T = df['temperature'].values * units.degC
r = df['r'].values * units('g/kg')
e = mpcalc.vapor_pressure(p, r)
Td = mpcalc.dewpoint(e)
wind_speed = df['speed'].values * units.meter / (units.second)
wind_dir = df['direction'].values * units.degrees
u, v = mpcalc.wind_components(wind_speed, wind_dir)

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

fig = plt.figure(figsize=(12., 9.))
fig.subplots_adjust(top=0.9,
                    bottom=0.1,
                    left=0.05,
                    right=0.96,
Ejemplo n.º 16
0
def plotter(fdict):
    """ Go """
    pgconn = get_dbconn('asos')
    ctx = get_autoplot_context(fdict, get_description())
    station = ctx['zstation']
    network = ctx['network']
    month = ctx['month']

    nt = NetworkTable(network)

    if month == 'all':
        months = range(1, 13)
    elif month == 'fall':
        months = [9, 10, 11]
    elif month == 'winter':
        months = [12, 1, 2]
    elif month == 'spring':
        months = [3, 4, 5]
    elif month == 'summer':
        months = [6, 7, 8]
    else:
        ts = datetime.datetime.strptime("2000-"+month+"-01", '%Y-%b-%d')
        # make sure it is length two for the trick below in SQL
        months = [ts.month, 999]

    df = read_sql("""
        SELECT tmpf::int as tmpf, dwpf,
        coalesce(mslp, alti * 33.8639, 1013.25) as slp
        from alldata where station = %s
        and drct is not null and dwpf is not null and dwpf <= tmpf
        and sknt > 3 and drct::int %% 10 = 0
        and extract(month from valid) in %s
        and report_type = 2
    """, pgconn, params=(station, tuple(months)))
    # Convert sea level pressure to station pressure
    df['pressure'] = mcalc.add_height_to_pressure(
        df['slp'].values * units('millibars'),
        nt.sts[station]['elevation'] * units('m')
    ).to(units('millibar'))
    # compute RH
    df['relh'] = mcalc.relative_humidity_from_dewpoint(
        df['tmpf'].values * units('degF'),
        df['dwpf'].values * units('degF')
    )
    # compute mixing ratio
    df['mixingratio'] = mcalc.mixing_ratio_from_relative_humidity(
        df['relh'].values,
        df['tmpf'].values * units('degF'),
        df['pressure'].values * units('millibars')
    )
    # compute pressure
    df['vapor_pressure'] = mcalc.vapor_pressure(
        df['pressure'].values * units('millibars'),
        df['mixingratio'].values * units('kg/kg')
    ).to(units('kPa'))

    means = df.groupby('tmpf').mean().copy()
    # compute dewpoint now
    means['dwpf'] = mcalc.dewpoint(
        means['vapor_pressure'].values * units('kPa')
    ).to(units('degF')).m
    means.reset_index(inplace=True)
    # compute RH again
    means['relh'] = mcalc.relative_humidity_from_dewpoint(
        means['tmpf'].values * units('degF'),
        means['dwpf'].values * units('degF')
    ) * 100.

    (fig, ax) = plt.subplots(1, 1, figsize=(8, 6))
    ax.bar(
        means['tmpf'].values - 0.5, means['dwpf'].values - 0.5,
        ec='green', fc='green', width=1
    )
    ax.grid(True, zorder=11)
    ax.set_title(("%s [%s]\nAverage Dew Point by Air Temperature (month=%s) "
                  "(%s-%s)\n"
                  "(must have 3+ hourly observations at the given temperature)"
                  ) % (nt.sts[station]['name'], station, month.upper(),
                       nt.sts[station]['archive_begin'].year,
                       datetime.datetime.now().year), size=10)

    ax.plot([0, 140], [0, 140], color='b')
    ax.set_ylabel("Dew Point [F]")
    y2 = ax.twinx()
    y2.plot(means['tmpf'].values, means['relh'].values, color='k')
    y2.set_ylabel("Relative Humidity [%] (black line)")
    y2.set_yticks([0, 5, 10, 25, 50, 75, 90, 95, 100])
    y2.set_ylim(0, 100)
    ax.set_ylim(0, means['tmpf'].max() + 2)
    ax.set_xlim(0, means['tmpf'].max() + 2)
    ax.set_xlabel(r"Air Temperature $^\circ$F")

    return fig, means[['tmpf', 'dwpf', 'relh']]
Ejemplo n.º 17
0
def entropy_plots(pressure,
                  temperature,
                  mixing_ratio,
                  altitude,
                  h0_std=2000,
                  ensemble_size=20,
                  ent_rate=np.arange(0, 2, 0.05),
                  entrain=False):
    """
    plotting the summarized entropy diagram with annotations and thermodynamic parameters
    """
    p = pressure * units('mbar')
    T = temperature * units('degC')
    q = mixing_ratio * units('kilogram/kilogram')
    qs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T), p)
    Td = mpcalc.dewpoint(mpcalc.vapor_pressure(p, q))  # dewpoint
    Tp = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')  # parcel profile

    # Altitude based on the hydrostatic eq.
    if len(altitude) == len(pressure):  # (1) altitudes for whole levels
        altitude = altitude * units('meter')
    elif len(altitude
             ) == 1:  # (2) known altitude where the soundings was launched
        z_surf = altitude.copy() * units('meter')
        # given altitude
        altitude = np.zeros((np.size(T))) * units('meter')
        for i in range(np.size(T)):
            altitude[i] = mpcalc.thickness_hydrostatic(
                p[:i + 1], T[:i + 1]) + z_surf  # Hypsometric Eq. for height
    else:
        print(
            '***NOTE***: the altitude at the surface is assumed 0 meter, and altitudes are derived based on the hypsometric equation'
        )
        altitude = np.zeros(
            (np.size(T))) * units('meter')  # surface is 0 meter
        for i in range(np.size(T)):
            altitude[i] = mpcalc.thickness_hydrostatic(
                p[:i + 1], T[:i + 1])  # Hypsometric Eq. for height

    # specific entropy [joule/(kg*K)]
    # sd : specific entropy of dry air
    # sm1 : specific entropy of airborne mositure in state 1 (water vapor)
    # sm2 : specific entropy of airborne mositure in state 2 (saturated water vapor)

    sd = entropy(T.magnitude, q.magnitude * 1e-6, p.magnitude)
    sm1 = entropy(T.magnitude, q.magnitude, p.magnitude)
    sm2 = entropy(T.magnitude, qs.magnitude, p.magnitude)
    ###############################

    # Water vapor calculations
    p_PWtop = min(p)
    #p_PWtop = max(200*units.mbar, min(p) + 1*units.mbar) # integrating until 200mb
    cwv = mpcalc.precipitable_water(Td, p,
                                    top=p_PWtop)  # column water vapor [mm]
    cwvs = mpcalc.precipitable_water(
        T, p, top=p_PWtop)  # saturated column water vapor [mm]
    crh = (cwv / cwvs) * 100.  # column relative humidity [%]

    #================================================
    # plotting MSE vertical profiles
    fig = plt.figure(figsize=[12, 8])
    ax = fig.add_axes([0.1, 0.1, 0.6, 0.8])
    ax.plot(sd, p, '-k', linewidth=2)
    ax.plot(sm1, p, '-b', linewidth=2)
    ax.plot(sm2, p, '-r', linewidth=2)

    # mse based on different percentages of relative humidity
    qr = np.zeros((9, np.size(qs))) * units('kilogram/kilogram')
    sm1_r = qr  # container
    for i in range(9):
        qr[i, :] = qs * 0.1 * (i + 1)
        sm1_r[i, :] = entropy(T.magnitude, qr[i, :].magnitude, p.magnitude)

    for i in range(9):
        ax.plot(sm1_r[i, :], p[:], '-', color='grey', linewidth=0.7)
        ax.text(sm1_r[i, 3].magnitude - 2, p[3].magnitude, str((i + 1) * 10))

    # drawing LCL and LFC levels
    [lcl_pressure, lcl_temperature] = mpcalc.lcl(p[0], T[0], Td[0])
    lcl_idx = np.argmin(np.abs(p.magnitude - lcl_pressure.magnitude))

    [lfc_pressure, lfc_temperature] = mpcalc.lfc(p, T, Td)
    lfc_idx = np.argmin(np.abs(p.magnitude - lfc_pressure.magnitude))

    # conserved mse of air parcel arising from 1000 hpa
    sm1_p = np.squeeze(np.ones((1, np.size(T))) * sm1[0])

    # illustration of CAPE
    el_pressure, el_temperature = mpcalc.el(p, T, Td)  # equilibrium level
    el_idx = np.argmin(np.abs(p.magnitude - el_pressure.magnitude))
    ELps = [el_pressure.magnitude
            ]  # Initialize an array of EL pressures for detrainment profile

    [CAPE, CIN] = mpcalc.cape_cin(p[:el_idx], T[:el_idx], Td[:el_idx],
                                  Tp[:el_idx])

    plt.plot(sm1_p, p, color='green', linewidth=2)
    #ax.fill_betweenx(p[lcl_idx:el_idx+1],sm1_p[lcl_idx:el_idx+1],sm2[lcl_idx:el_idx+1],interpolate=True
    #                ,color='green',alpha='0.3')

    ax.fill_betweenx(p, sd, sm1, color='deepskyblue', alpha='0.5')
    ax.set_xlabel('Specific entropies: sd, sm, sm_sat [J K$^{-1}$ kg$^{-1}$]',
                  fontsize=14)
    ax.set_ylabel('Pressure [hPa]', fontsize=14)
    ax.set_xticks([0, 50, 100, 150, 200, 250, 300, 350])
    ax.set_xlim([0, 440])
    ax.set_ylim(1030, 120)

    if entrain is True:
        # Depict Entraining parcels
        # Parcel mass solves dM/dz = eps*M, solution is M = exp(eps*Z)
        # M=1 at ground without loss of generality

        # Distribution of surface parcel h offsets
        h0offsets = np.sort(np.random.normal(
            0, h0_std, ensemble_size)) * units('joule/kilogram')
        # Distribution of entrainment rates
        entrainment_rates = ent_rate / (units('km'))

        for h0offset in h0offsets:

            h4ent = sm1.copy()
            h4ent[0] += h0offset

            for eps in entrainment_rates:

                M = np.exp(eps * (altitude - altitude[0])).to('dimensionless')
                # dM is the mass contribution at each level, with 1 at the origin level.
                M[0] = 0
                dM = np.gradient(M)
                # parcel mass is a sum of all the dM's at each level
                # conserved linearly-mixed variables like h are weighted averages
                if eps.magnitude == 0.0:
                    hent = np.ones(len(h4ent)) * h4ent[0]  # no mixing
                else:
                    hent = np.cumsum(dM * h4ent) / np.cumsum(dM)
                # Boolean for positive buoyancy, and its topmost altitude (index) where curve is clippes
                posboy = (hent > sm2)
                posboy[0] = True  # so there is always a detrainment level

                # defining the first EL by posboy as the detrainment layer, swiching from positive buoyancy to
                # negative buoyancy (0 to 1) and skipping the surface
                ELindex_ent = 0
                for idx in range(len(posboy) - 1):
                    if posboy[idx + 1] == 0 and posboy[idx] == 1 and idx > 0:
                        ELindex_ent = idx
                        break

                # Plot the curve
                plt.plot(hent[0:ELindex_ent + 2],
                         p[0:ELindex_ent + 2],
                         linewidth=0.6,
                         color='g')
                #plt.plot( hent[0:], p[0:], linewidth=0.6, color='g')
                # Keep a list for a histogram plot (detrainment profile)
                if p[ELindex_ent].magnitude < lfc_pressure.magnitude:  # buoyant parcels only
                    ELps.append(p[ELindex_ent].magnitude)

        # Plot a crude histogram of parcel detrainment levels
        NBINS = 20
        pbins = np.linspace(1000, 150,
                            num=NBINS)  # pbins for detrainment levels
        hist = np.zeros((len(pbins) - 1))
        for x in ELps:
            for i in range(len(pbins) - 1):
                if (x < pbins[i]) & (x >= pbins[i + 1]):
                    hist[i] += 1
                    break

        det_per = hist / sum(hist) * 100
        # percentages of detrainment ensumbles at levels

        ax2 = fig.add_axes([0.705, 0.1, 0.1, 0.8], facecolor=None)
        ax2.barh(pbins[1:],
                 det_per,
                 color='lightgrey',
                 edgecolor='k',
                 height=15 * (20 / NBINS))
        ax2.set_xlim([0, 100])
        ax2.set_xticks([0, 20, 40, 60, 80, 100])
        ax2.set_ylim([1030, 120])
        ax2.set_xlabel('Detrainment [%]')
        ax2.grid()
        ax2.set_zorder(2)

        ax.plot([400, 400], [1100, 0])
        ax.annotate('Detrainment', xy=(362, 320), color='dimgrey')
        ax.annotate('ensemble: ' + str(ensemble_size * len(entrainment_rates)),
                    xy=(364, 340),
                    color='dimgrey')
        ax.annotate('Detrainment', xy=(362, 380), color='dimgrey')
        ax.annotate(' scale: 0 - 2 km', xy=(365, 400), color='dimgrey')

        # Overplots on the mess: undilute parcel and CAPE, etc.
        ax.plot((1, 1) * sm1[0], (1, 0) * (p[0]), color='g', linewidth=2)

        # Replot the sounding on top of all that mess
        ax.plot(sm2, p, color='r', linewidth=1.5)
        ax.plot(sm1, p, color='b', linewidth=1.5)

        # label LCL and LCF
        ax.plot((sm2[lcl_idx] + (-2000, 2000) * units('joule/kilogram')),
                lcl_pressure + (0, 0) * units('mbar'),
                color='orange',
                linewidth=3)
        ax.plot((sm2[lfc_idx] + (-2000, 2000) * units('joule/kilogram')),
                lfc_pressure + (0, 0) * units('mbar'),
                color='magenta',
                linewidth=3)

    # Plot a crude histogram of parcel detrainment levels
    # Text parts
    ax.text(30, pressure[3], 'RH (%)', fontsize=11, color='k')
    ax.text(20,
            200,
            'CAPE = ' + str(np.around(CAPE.magnitude, decimals=2)) + ' [J/kg]',
            fontsize=12,
            color='green')
    ax.text(20,
            250,
            'CIN = ' + str(np.around(CIN.magnitude, decimals=2)) + ' [J/kg]',
            fontsize=12,
            color='green')
    ax.text(20,
            300,
            'LCL = ' + str(np.around(lcl_pressure.magnitude, decimals=2)) +
            ' [hpa]',
            fontsize=12,
            color='darkorange')
    ax.text(20,
            350,
            'LFC = ' + str(np.around(lfc_pressure.magnitude, decimals=2)) +
            ' [hpa]',
            fontsize=12,
            color='magenta')
    ax.text(20,
            400,
            'CWV = ' + str(np.around(cwv.magnitude, decimals=2)) + ' [mm]',
            fontsize=12,
            color='deepskyblue')
    ax.text(20,
            450,
            'CRH = ' + str(np.around(crh.magnitude, decimals=2)) + ' [%]',
            fontsize=12,
            color='blue')
    ax.legend(['DEnt', 'MEnt', 'SMEnt'], fontsize=12, loc=1)

    ax.set_zorder(3)

    return (ax)
Ejemplo n.º 18
0
def main():
    img_dir = Path("hail_plots/soundings/")

    if not img_dir.exists():
        img_dir.mkdir(parents=True)

    data_dir = Path("/HOME/huziy/skynet3_rech1/hail/soundings_from_erai/")

    # dates = [datetime(1991, 9, 7), datetime(1991, 9, 7, 6), datetime(1991, 9, 7, 12), datetime(1991, 9, 7, 18),
    #          datetime(1991, 9, 8, 0), datetime(1991, 9, 8, 18)]
    #
    # dates.extend([datetime(1991, 9, 6, 0), datetime(1991, 9, 6, 6), datetime(1991, 9, 6, 12), datetime(1991, 9, 6, 18)])
    #
    # dates = [datetime(1990, 7, 7), datetime(2010, 7, 12), datetime(1991, 9, 8, 0)]

    dates_s = """
- 07/09/1991 12:00
- 07/09/1991 18:00
- 08/09/1991 00:00
- 08/09/1991 06:00
- 08/09/1991 12:00
- 13/09/1991 12:00
- 13/09/1991 18:00
- 14/09/1991 00:00
- 14/09/1991 06:00
- 14/09/1991 12:00
    """

    dates = [
        datetime.strptime(line.strip()[1:].strip(), "%d/%m/%Y %H:%M")
        for line in dates_s.split("\n") if line.strip() != ""
    ]

    def __date_parser(s):
        return pd.datetime.strptime(s, '%Y-%m-%d %H:%M:%S')

    tt = pd.read_csv(data_dir.joinpath("TT.csv"),
                     index_col=0,
                     parse_dates=['Time'])
    uu = pd.read_csv(data_dir.joinpath("UU.csv"),
                     index_col=0,
                     parse_dates=['Time'])
    vv = pd.read_csv(data_dir.joinpath("VV.csv"),
                     index_col=0,
                     parse_dates=['Time'])
    hu = pd.read_csv(data_dir.joinpath("HU.csv"),
                     index_col=0,
                     parse_dates=['Time'])

    print(tt.head())
    print([c for c in tt])
    print(list(tt.columns.values))

    temp_perturbation_degc = 0

    for the_date in dates:

        p = np.array([float(c) for c in tt])

        fig = plt.figure(figsize=(9, 9))
        skew = SkewT(fig)

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

        tsel = tt.select(lambda d: d == the_date)
        usel = uu.select(lambda d: d == the_date)
        vsel = vv.select(lambda d: d == the_date)
        husel = hu.select(lambda d: d == the_date)

        tvals = tsel.values.mean(axis=0)
        uvals = usel.values.mean(axis=0) * mul_mpers_per_knot
        vvals = vsel.values.mean(axis=0) * mul_mpers_per_knot
        huvals = husel.values.mean(axis=0) * units("g/kg")

        # ignore the lowest level
        all_vars = [p, tvals, uvals, vvals, huvals]

        for i in range(len(all_vars)):
            all_vars[i] = all_vars[i][:-5]

        p, tvals, uvals, vvals, huvals = all_vars

        assert len(p) == len(huvals)

        tdvals = calc.dewpoint(
            calc.vapor_pressure(p * units.mbar, huvals).to(units.mbar))

        print(tvals, tdvals)
        # Calculate full parcel profile and add to plot as black line
        parcel_profile = calc.parcel_profile(
            p[::-1] * units.mbar,
            (tvals[-1] + temp_perturbation_degc) * units.degC,
            tdvals[-1]).to('degC')
        parcel_profile = parcel_profile[::-1]
        skew.plot(p, parcel_profile, 'k', linewidth=2)

        # Example of coloring area between profiles
        greater = tvals * units.degC >= parcel_profile
        skew.ax.fill_betweenx(p,
                              tvals,
                              parcel_profile,
                              where=greater,
                              facecolor='blue',
                              alpha=0.4)
        skew.ax.fill_betweenx(p,
                              tvals,
                              parcel_profile,
                              where=~greater,
                              facecolor='red',
                              alpha=0.4)

        skew.plot(p, tvals, "r")
        skew.plot(p, tdvals, "g")

        skew.plot_barbs(p, uvals, vvals)

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

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

        plt.title("{} (dT={})".format(the_date, temp_perturbation_degc))

        img_path = "{}_dT={}.png".format(the_date.strftime("%Y%m%d_%H%M%S"),
                                         temp_perturbation_degc)
        img_path = img_dir.joinpath(img_path)
        fig.savefig(str(img_path), bbox_inches="tight")

        plt.close(fig)
Ejemplo n.º 19
0
def main():
    img_dir = Path("hail_plots/soundings/")

    if not img_dir.exists():
        img_dir.mkdir(parents=True)


    data_dir = Path("/HOME/huziy/skynet3_rech1/hail/soundings_from_erai/")

    # dates = [datetime(1991, 9, 7), datetime(1991, 9, 7, 6), datetime(1991, 9, 7, 12), datetime(1991, 9, 7, 18),
    #          datetime(1991, 9, 8, 0), datetime(1991, 9, 8, 18)]
    #
    # dates.extend([datetime(1991, 9, 6, 0), datetime(1991, 9, 6, 6), datetime(1991, 9, 6, 12), datetime(1991, 9, 6, 18)])
    #
    # dates = [datetime(1990, 7, 7), datetime(2010, 7, 12), datetime(1991, 9, 8, 0)]



    dates_s = """
- 07/09/1991 12:00
- 07/09/1991 18:00
- 08/09/1991 00:00
- 08/09/1991 06:00
- 08/09/1991 12:00
- 13/09/1991 12:00
- 13/09/1991 18:00
- 14/09/1991 00:00
- 14/09/1991 06:00
- 14/09/1991 12:00
    """

    dates = [datetime.strptime(line.strip()[1:].strip(), "%d/%m/%Y %H:%M") for line in dates_s.split("\n") if line.strip() != ""]




    def __date_parser(s):
        return pd.datetime.strptime(s, '%Y-%m-%d %H:%M:%S')


    tt = pd.read_csv(data_dir.joinpath("TT.csv"), index_col=0, parse_dates=['Time'])
    uu = pd.read_csv(data_dir.joinpath("UU.csv"), index_col=0, parse_dates=['Time'])
    vv = pd.read_csv(data_dir.joinpath("VV.csv"), index_col=0, parse_dates=['Time'])
    hu = pd.read_csv(data_dir.joinpath("HU.csv"), index_col=0, parse_dates=['Time'])


    print(tt.head())
    print([c for c in tt])
    print(list(tt.columns.values))




    temp_perturbation_degc = 0

    for the_date in dates:

        p = np.array([float(c) for c in tt])

        fig = plt.figure(figsize=(9, 9))
        skew = SkewT(fig)

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


        tsel = tt.select(lambda d: d == the_date)
        usel = uu.select(lambda d: d == the_date)
        vsel = vv.select(lambda d: d == the_date)
        husel = hu.select(lambda d: d == the_date)


        tvals = tsel.values.mean(axis=0)
        uvals = usel.values.mean(axis=0) * mul_mpers_per_knot
        vvals = vsel.values.mean(axis=0) * mul_mpers_per_knot
        huvals = husel.values.mean(axis=0) * units("g/kg")


        # ignore the lowest level
        all_vars = [p, tvals, uvals, vvals, huvals]

        for i in range(len(all_vars)):
            all_vars[i] = all_vars[i][:-5]

        p, tvals, uvals, vvals, huvals = all_vars


        assert len(p) == len(huvals)

        tdvals = calc.dewpoint(calc.vapor_pressure(p * units.mbar, huvals).to(units.mbar))


        print(tvals, tdvals)
        # Calculate full parcel profile and add to plot as black line
        parcel_profile = calc.parcel_profile(p[::-1] * units.mbar, (tvals[-1] + temp_perturbation_degc) * units.degC, tdvals[-1]).to('degC')
        parcel_profile = parcel_profile[::-1]
        skew.plot(p, parcel_profile, 'k', linewidth=2)



        # Example of coloring area between profiles
        greater = tvals * units.degC >= parcel_profile
        skew.ax.fill_betweenx(p, tvals, parcel_profile, where=greater, facecolor='blue', alpha=0.4)
        skew.ax.fill_betweenx(p, tvals, parcel_profile, where=~greater, facecolor='red', alpha=0.4)



        skew.plot(p, tvals, "r")
        skew.plot(p, tdvals, "g")

        skew.plot_barbs(p, uvals, vvals)

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


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

        plt.title("{} (dT={})".format(the_date, temp_perturbation_degc))

        img_path = "{}_dT={}.png".format(the_date.strftime("%Y%m%d_%H%M%S"), temp_perturbation_degc)
        img_path = img_dir.joinpath(img_path)
        fig.savefig(str(img_path), bbox_inches="tight")

        plt.close(fig)
Ejemplo n.º 20
0
def test_vapor_pressure():
    """Test vapor pressure calculation."""
    assert_almost_equal(vapor_pressure(998. * units.mbar, 0.04963),
                        73.74925 * units.mbar, 5)
Ejemplo n.º 21
0
    vgrd = v[j, 2:29, :, lugar]
    q = q[j, 2:29, :, lugar]
    t = t[j, 2:29, :, lugar]
    omega = w[j, 2:29, :, lugar]

    ## hay que transformar omega a w:
    rgas = 287.058
    g = 9.80665
    vvel = np.zeros([int((omega.shape)[0]), int((omega.shape)[1])])
    for ii in range(0, int((omega.shape)[0])):
        rho = niveles[ii] / (rgas * t[ii, :])
        a = -omega[ii, :] / (rho * g)
        vvel[ii, :] = a

    ## calculo la temperatura potencial equivalente
    e = mpcalc.vapor_pressure(1000. * units.mbar, q)
    td = mpcalc.dewpoint(e)
    titae = np.zeros([int((omega.shape)[0]), int((omega.shape)[1])])
    for iii in range(0, int((omega.shape)[0])):
        titae[iii, :] = mpcalc.equivalent_potential_temperature(
            (niveles[iii] * 100) * units.pascal, t[iii, :] * units.kelvin,
            td[iii, :])
    titae = ndimage.gaussian_filter(titae, sigma=1, order=0)

    ## paso el geopotencial del terreno a presion para poder graficarlo junto a lo demas
    z_sup = z_sup[0, :, lugar_z] / 9.80665
    press = (100000 - (1.2) * 9.81 * (z_sup)) / 100

    ####### GRAFICADO ########
    if i == 0:
        fig = plt.figure(figsize=(18, 12))
Ejemplo n.º 22
0
def plotter(fdict):
    """ Go """
    pgconn = get_dbconn('asos')
    ctx = get_autoplot_context(fdict, get_description())
    station = ctx['zstation']
    network = ctx['network']
    nt = NetworkTable(network)
    year = ctx['year']
    varname = ctx['var']

    df = read_sql("""
        SELECT extract(year from valid) as year,
        coalesce(mslp, alti * 33.8639, 1013.25) as slp,
        extract(doy from valid) as doy, tmpf, dwpf from alldata
        where station = %s and dwpf > -50 and dwpf < 90 and
        tmpf > -50 and tmpf < 120 and valid > '1950-01-01'
        and report_type = 2
    """,
                  pgconn,
                  params=(station, ),
                  index_col=None)
    # compute RH
    df['relh'] = mcalc.relative_humidity_from_dewpoint(
        df['tmpf'].values * units('degF'), df['dwpf'].values * units('degF'))
    # saturation vapor pressure
    # Convert sea level pressure to station pressure
    df['pressure'] = mcalc.add_height_to_pressure(
        df['slp'].values * units('millibars'),
        nt.sts[station]['elevation'] * units('m')).to(units('millibar'))
    # Compute the relative humidity
    df['relh'] = mcalc.relative_humidity_from_dewpoint(
        df['tmpf'].values * units('degF'), df['dwpf'].values * units('degF'))
    # Compute the mixing ratio
    df['mixing_ratio'] = mcalc.mixing_ratio_from_relative_humidity(
        df['relh'].values, df['tmpf'].values * units('degF'),
        df['pressure'].values * units('millibars'))
    # Compute the saturation mixing ratio
    df['saturation_mixingratio'] = mcalc.saturation_mixing_ratio(
        df['pressure'].values * units('millibars'),
        df['tmpf'].values * units('degF'))
    df['vapor_pressure'] = mcalc.vapor_pressure(
        df['pressure'].values * units('millibars'),
        df['mixing_ratio'].values * units('kg/kg')).to(units('kPa'))
    df['saturation_vapor_pressure'] = mcalc.vapor_pressure(
        df['pressure'].values * units('millibars'),
        df['saturation_mixingratio'].values * units('kg/kg')).to(units('kPa'))
    df['vpd'] = df['saturation_vapor_pressure'] - df['vapor_pressure']

    dailymeans = df[['year', 'doy', varname]].groupby(['year', 'doy']).mean()
    dailymeans = dailymeans.reset_index()

    df2 = dailymeans[['doy', varname]].groupby('doy').describe()

    dyear = df[df['year'] == year]
    df3 = dyear[['doy', varname]].groupby('doy').describe()
    df3[(varname, 'diff')] = df3[(varname, 'mean')] - df2[(varname, 'mean')]

    (fig, ax) = plt.subplots(2, 1, figsize=(8, 6))
    multiplier = 1000. if varname == 'mixing_ratio' else 10.

    ax[0].fill_between(df2[(varname, 'min')].index.values,
                       df2[(varname, 'min')].values * multiplier,
                       df2[(varname, 'max')].values * multiplier,
                       color='gray')

    ax[0].plot(df2[(varname, 'mean')].index.values,
               df2[(varname, 'mean')].values * multiplier,
               label="Climatology")
    ax[0].plot(df3[(varname, 'mean')].index.values,
               df3[(varname, 'mean')].values * multiplier,
               color='r',
               label="%s" % (year, ))

    ax[0].set_title(("%s [%s]\nDaily Mean Surface %s") %
                    (station, nt.sts[station]['name'], PDICT[varname]))
    lbl = ("Mixing Ratio ($g/kg$)"
           if varname == 'mixing_ratio' else PDICT[varname])
    ax[0].set_ylabel(lbl)
    ax[0].set_xlim(0, 366)
    ax[0].set_ylim(bottom=0)
    ax[0].set_xticks(
        (1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365))
    ax[0].set_xticklabels(calendar.month_abbr[1:])
    ax[0].grid(True)
    ax[0].legend(loc=2, fontsize=10)

    cabove = 'b' if varname == 'mixing_ratio' else 'r'
    cbelow = 'r' if cabove == 'b' else 'b'
    rects = ax[1].bar(df3[(varname, 'diff')].index.values,
                      df3[(varname, 'diff')].values * multiplier,
                      facecolor=cabove,
                      edgecolor=cabove)
    for rect in rects:
        if rect.get_height() < 0.:
            rect.set_facecolor(cbelow)
            rect.set_edgecolor(cbelow)

    plunits = '$g/kg$' if varname == 'mixing_ratio' else 'hPa'
    ax[1].set_ylabel("%.0f Departure (%s)" % (year, plunits))
    ax[1].set_xlim(0, 366)
    ax[1].set_xticks(
        (1, 32, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 365))
    ax[1].set_xticklabels(calendar.month_abbr[1:])
    ax[1].grid(True)
    return fig, df3
Ejemplo n.º 23
0
def test_vapor_pressure():
    """Test vapor pressure calculation."""
    assert_almost_equal(vapor_pressure(998. * units.mbar, 0.04963),
                        73.74925 * units.mbar, 5)
Ejemplo n.º 24
0
def plotter(fdict):
    """ Go """
    pgconn = get_dbconn("asos")
    ctx = get_autoplot_context(fdict, get_description())
    station = ctx["zstation"]
    month = ctx["month"]

    if month == "all":
        months = range(1, 13)
    elif month == "fall":
        months = [9, 10, 11]
    elif month == "winter":
        months = [12, 1, 2]
    elif month == "spring":
        months = [3, 4, 5]
    elif month == "summer":
        months = [6, 7, 8]
    else:
        ts = datetime.datetime.strptime("2000-" + month + "-01", "%Y-%b-%d")
        # make sure it is length two for the trick below in SQL
        months = [ts.month, 999]

    df = read_sql(
        """
        SELECT tmpf::int as tmpf, dwpf, relh,
        coalesce(mslp, alti * 33.8639, 1013.25) as slp
        from alldata where station = %s
        and drct is not null and dwpf is not null and dwpf <= tmpf
        and sknt > 3 and drct::int %% 10 = 0
        and extract(month from valid) in %s
        and report_type = 2
    """,
        pgconn,
        params=(station, tuple(months)),
    )
    if df.empty:
        raise NoDataFound("No Data Found.")
    # Convert sea level pressure to station pressure
    df["pressure"] = mcalc.add_height_to_pressure(
        df["slp"].values * units("millibars"),
        ctx["_nt"].sts[station]["elevation"] * units("m"),
    ).to(units("millibar"))
    # compute mixing ratio
    df["mixingratio"] = mcalc.mixing_ratio_from_relative_humidity(
        df["relh"].values * units("percent"),
        df["tmpf"].values * units("degF"),
        df["pressure"].values * units("millibars"),
    )
    # compute pressure
    df["vapor_pressure"] = mcalc.vapor_pressure(
        df["pressure"].values * units("millibars"),
        df["mixingratio"].values * units("kg/kg"),
    ).to(units("kPa"))

    means = df.groupby("tmpf").mean().copy()
    # compute dewpoint now
    means["dwpf"] = (
        mcalc.dewpoint(means["vapor_pressure"].values * units("kPa"))
        .to(units("degF"))
        .m
    )
    means.reset_index(inplace=True)
    # compute RH again
    means["relh"] = (
        mcalc.relative_humidity_from_dewpoint(
            means["tmpf"].values * units("degF"),
            means["dwpf"].values * units("degF"),
        )
        * 100.0
    )

    (fig, ax) = plt.subplots(1, 1, figsize=(8, 6))
    ax.bar(
        means["tmpf"].values - 0.5,
        means["dwpf"].values - 0.5,
        ec="green",
        fc="green",
        width=1,
    )
    ax.grid(True, zorder=11)
    ab = ctx["_nt"].sts[station]["archive_begin"]
    if ab is None:
        raise NoDataFound("Unknown station metadata.")
    ax.set_title(
        (
            "%s [%s]\nAverage Dew Point by Air Temperature (month=%s) "
            "(%s-%s)\n"
            "(must have 3+ hourly observations at the given temperature)"
        )
        % (
            ctx["_nt"].sts[station]["name"],
            station,
            month.upper(),
            ab.year,
            datetime.datetime.now().year,
        ),
        size=10,
    )

    ax.plot([0, 140], [0, 140], color="b")
    ax.set_ylabel("Dew Point [F]")
    y2 = ax.twinx()
    y2.plot(means["tmpf"].values, means["relh"].values, color="k")
    y2.set_ylabel("Relative Humidity [%] (black line)")
    y2.set_yticks([0, 5, 10, 25, 50, 75, 90, 95, 100])
    y2.set_ylim(0, 100)
    ax.set_ylim(0, means["tmpf"].max() + 2)
    ax.set_xlim(0, means["tmpf"].max() + 2)
    ax.set_xlabel(r"Air Temperature $^\circ$F")

    return fig, means[["tmpf", "dwpf", "relh"]]
Ejemplo n.º 25
0
def plotter(fdict):
    """ Go """
    pgconn = get_dbconn('asos')
    ctx = get_autoplot_context(fdict, get_description())

    station = ctx['zstation']
    network = ctx['network']
    month = ctx['month']

    nt = NetworkTable(network)

    if month == 'all':
        months = range(1, 13)
    elif month == 'fall':
        months = [9, 10, 11]
    elif month == 'winter':
        months = [12, 1, 2]
    elif month == 'spring':
        months = [3, 4, 5]
    elif month == 'summer':
        months = [6, 7, 8]
    else:
        ts = datetime.datetime.strptime("2000-" + month + "-01", '%Y-%b-%d')
        # make sure it is length two for the trick below in SQL
        months = [ts.month, 999]

    df = read_sql("""
        SELECT drct::int as t, dwpf, tmpf, relh,
        coalesce(mslp, alti * 33.8639, 1013.25) as slp
        from alldata where station = %s
        and drct is not null and dwpf is not null and dwpf <= tmpf
        and sknt > 3 and drct::int %% 10 = 0
        and extract(month from valid) in %s
        and report_type = 2
    """,
                  pgconn,
                  params=(station, tuple(months)))
    # Convert sea level pressure to station pressure
    df['pressure'] = mcalc.add_height_to_pressure(
        df['slp'].values * units('millibars'),
        nt.sts[station]['elevation'] * units('m')).to(units('millibar'))
    # compute mixing ratio
    df['mixingratio'] = mcalc.mixing_ratio_from_relative_humidity(
        df['relh'].values * units('percent'),
        df['tmpf'].values * units('degF'),
        df['pressure'].values * units('millibars'))
    # compute pressure
    df['vapor_pressure'] = mcalc.vapor_pressure(
        df['pressure'].values * units('millibars'),
        df['mixingratio'].values * units('kg/kg')).to(units('kPa'))

    means = df.groupby('t').mean().copy()
    # compute dewpoint now
    means['dwpf'] = mcalc.dewpoint(means['vapor_pressure'].values *
                                   units('kPa')).to(units('degF')).m

    (fig, ax) = plt.subplots(1, 1)
    ax.bar(means.index.values,
           means['dwpf'].values,
           ec='green',
           fc='green',
           width=10,
           align='center')
    ax.grid(True, zorder=11)
    ax.set_title(("%s [%s]\nAverage Dew Point by Wind Direction (month=%s) "
                  "(%s-%s)\n"
                  "(must have 3+ hourly obs > 3 knots at given direction)") %
                 (nt.sts[station]['name'], station, month.upper(),
                  max([1973, nt.sts[station]['archive_begin'].year
                       ]), datetime.datetime.now().year),
                 size=10)

    ax.set_ylabel("Dew Point [F]")
    ax.set_ylim(means['dwpf'].min() - 5, means['dwpf'].max() + 5)
    ax.set_xlim(-5, 365)
    ax.set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360])
    ax.set_xticklabels(['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW', 'N'])
    ax.set_xlabel("Wind Direction")

    return fig, means['dwpf']
Ejemplo n.º 26
0
def msed_plots(pressure,
               temperature,
               mixing_ratio,
               h0_std=2000,
               ensemble_size=20,
               ent_rate=np.arange(0, 2, 0.05),
               entrain=False):
    """
    plotting the summarized static energy diagram with annotations and thermodynamic parameters
    """
    p = pressure * units('mbar')
    T = temperature * units('degC')
    q = mixing_ratio * units('kilogram/kilogram')
    qs = mpcalc.mixing_ratio(mpcalc.saturation_vapor_pressure(T), p)
    Td = mpcalc.dewpoint(mpcalc.vapor_pressure(p, q))  # dewpoint
    Tp = mpcalc.parcel_profile(p, T[0], Td[0]).to('degC')  # parcel profile

    # Altitude based on the hydrostatic eq.
    altitude = np.zeros((np.size(T))) * units('meter')  # surface is 0 meter
    for i in range(np.size(T)):
        altitude[i] = mpcalc.thickness_hydrostatic(
            p[:i + 1], T[:i + 1])  # Hypsometric Eq. for height

    # Static energy calculations
    mse = mpcalc.moist_static_energy(altitude, T, q)
    mse_s = mpcalc.moist_static_energy(altitude, T, qs)
    dse = mpcalc.dry_static_energy(altitude, T)

    # Water vapor calculations
    p_PWtop = max(200 * units.mbar,
                  min(p) + 1 * units.mbar)  # integrating until 200mb
    cwv = mpcalc.precipitable_water(Td, p,
                                    top=p_PWtop)  # column water vapor [mm]
    cwvs = mpcalc.precipitable_water(
        T, p, top=p_PWtop)  # saturated column water vapor [mm]
    crh = (cwv / cwvs) * 100.  # column relative humidity [%]

    #================================================
    # plotting MSE vertical profiles
    fig = plt.figure(figsize=[12, 8])
    ax = fig.add_axes([0.1, 0.1, 0.6, 0.8])
    ax.plot(dse, p, '-k', linewidth=2)
    ax.plot(mse, p, '-b', linewidth=2)
    ax.plot(mse_s, p, '-r', linewidth=2)

    # mse based on different percentages of relative humidity
    qr = np.zeros((9, np.size(qs))) * units('kilogram/kilogram')
    mse_r = qr * units('joule/kilogram')  # container
    for i in range(9):
        qr[i, :] = qs * 0.1 * (i + 1)
        mse_r[i, :] = mpcalc.moist_static_energy(altitude, T, qr[i, :])

    for i in range(9):
        ax.plot(mse_r[i, :], p[:], '-', color='grey', linewidth=0.7)
        ax.text(mse_r[i, 3].magnitude / 1000 - 1, p[3].magnitude,
                str((i + 1) * 10))

    # drawing LCL and LFC levels
    [lcl_pressure, lcl_temperature] = mpcalc.lcl(p[0], T[0], Td[0])
    lcl_idx = np.argmin(np.abs(p.magnitude - lcl_pressure.magnitude))

    [lfc_pressure, lfc_temperature] = mpcalc.lfc(p, T, Td)
    lfc_idx = np.argmin(np.abs(p.magnitude - lfc_pressure.magnitude))

    # conserved mse of air parcel arising from 1000 hpa
    mse_p = np.squeeze(np.ones((1, np.size(T))) * mse[0].magnitude)

    # illustration of CAPE
    el_pressure, el_temperature = mpcalc.el(p, T, Td)  # equilibrium level
    el_idx = np.argmin(np.abs(p.magnitude - el_pressure.magnitude))
    ELps = [el_pressure.magnitude
            ]  # Initialize an array of EL pressures for detrainment profile

    [CAPE, CIN] = mpcalc.cape_cin(p[:el_idx], T[:el_idx], Td[:el_idx],
                                  Tp[:el_idx])

    plt.plot(mse_p, p, color='green', linewidth=2)
    ax.fill_betweenx(p[lcl_idx:el_idx + 1],
                     mse_p[lcl_idx:el_idx + 1],
                     mse_s[lcl_idx:el_idx + 1],
                     interpolate=True,
                     color='green',
                     alpha='0.3')

    ax.fill_betweenx(p, dse, mse, color='deepskyblue', alpha='0.5')
    ax.set_xlabel('Specific static energies: s, h, hs [kJ kg$^{-1}$]',
                  fontsize=14)
    ax.set_ylabel('Pressure [hpa]', fontsize=14)
    ax.set_xticks([280, 300, 320, 340, 360, 380])
    ax.set_xlim([280, 390])
    ax.set_ylim(1030, 120)

    if entrain is True:
        # Depict Entraining parcels
        # Parcel mass solves dM/dz = eps*M, solution is M = exp(eps*Z)
        # M=1 at ground without loss of generality

        # Distribution of surface parcel h offsets
        H0STDEV = h0_std  # J/kg
        h0offsets = np.sort(np.random.normal(
            0, H0STDEV, ensemble_size)) * units('joule/kilogram')
        # Distribution of entrainment rates
        entrainment_rates = ent_rate / (units('km'))

        for h0offset in h0offsets:

            h4ent = mse.copy()
            h4ent[0] += h0offset

            for eps in entrainment_rates:

                M = np.exp(eps * (altitude - altitude[0])).to('dimensionless')
                # dM is the mass contribution at each level, with 1 at the origin level.
                M[0] = 0
                dM = np.gradient(M)

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

                # Boolean for positive buoyancy, and its topmost altitude (index) where curve is clippes
                posboy = (hent > mse_s)
                posboy[0] = True  # so there is always a detrainment level

                ELindex_ent = np.max(np.where(posboy))
                # Plot the curve
                plt.plot(hent[0:ELindex_ent + 2],
                         p[0:ELindex_ent + 2],
                         linewidth=0.25,
                         color='g')
                # Keep a list for a histogram plot (detrainment profile)
                if p[ELindex_ent].magnitude < lfc_pressure.magnitude:  # buoyant parcels only
                    ELps.append(p[ELindex_ent].magnitude)

        # Plot a crude histogram of parcel detrainment levels
        NBINS = 20
        pbins = np.linspace(1000, 150,
                            num=NBINS)  # pbins for detrainment levels
        hist = np.zeros((len(pbins) - 1))
        for x in ELps:
            for i in range(len(pbins) - 1):
                if (x < pbins[i]) & (x >= pbins[i + 1]):
                    hist[i] += 1
                    break

        det_per = hist / sum(hist) * 100
        # percentages of detrainment ensumbles at levels

        ax2 = fig.add_axes([0.705, 0.1, 0.1, 0.8], facecolor=None)
        ax2.barh(pbins[1:],
                 det_per,
                 color='lightgrey',
                 edgecolor='k',
                 height=15 * (20 / NBINS))
        ax2.set_xlim([0, max(det_per)])
        ax2.set_ylim([1030, 120])
        ax2.set_xlabel('Detrainment [%]')
        ax2.grid()
        ax2.set_zorder(2)

        ax.plot([400, 400], [1100, 0])
        ax.annotate('Detrainment', xy=(362, 320), color='dimgrey')
        ax.annotate('ensemble: ' + str(ensemble_size * len(entrainment_rates)),
                    xy=(364, 340),
                    color='dimgrey')
        ax.annotate('Detrainment', xy=(362, 380), color='dimgrey')
        ax.annotate(' scale: 0 - 2 km', xy=(365, 400), color='dimgrey')

        # Overplots on the mess: undilute parcel and CAPE, etc.
        ax.plot((1, 1) * mse[0], (1, 0) * (p[0]), color='g', linewidth=2)

        # Replot the sounding on top of all that mess
        ax.plot(mse_s, p, color='r', linewidth=1.5)
        ax.plot(mse, p, color='b', linewidth=1.5)

        # label LCL and LCF
        ax.plot((mse_s[lcl_idx] + (-2000, 2000) * units('joule/kilogram')),
                lcl_pressure + (0, 0) * units('mbar'),
                color='orange',
                linewidth=3)
        ax.plot((mse_s[lfc_idx] + (-2000, 2000) * units('joule/kilogram')),
                lfc_pressure + (0, 0) * units('mbar'),
                color='magenta',
                linewidth=3)

    ### Internal waves (100m adiabatic displacements, assumed adiabatic: conserves s, sv, h).
    #dZ = 100 *mpunits.units.meter
    dp = 1000 * units.pascal

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

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

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

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

        # Whiskers on the data plots
        ax.plot((mse_s[idx] + dhs * (-1, 1)),
                p[idx] + dp * (-1, 1),
                linewidth=3,
                color='r')
        ax.plot((dse[idx] * (1, 1)),
                p[idx] + dp * (-1, 1),
                linewidth=3,
                color='k')
        ax.plot((mse[idx] * (1, 1)),
                p[idx] + dp * (-1, 1),
                linewidth=3,
                color='b')

        # annotation to explain it
        if ilev == 400 * ilev.units:
            ax.plot(360 * mse_s.units + dhs * (-1, 1) / 1000,
                    440 * units('mbar') + dp * (-1, 1),
                    linewidth=3,
                    color='r')
            ax.annotate('+/- 10mb', xy=(362, 440), fontsize=8)
            ax.annotate(' adiabatic displacement', xy=(362, 460), fontsize=8)

    # Plot a crude histogram of parcel detrainment levels
    # Text parts
    ax.text(290, pressure[3], 'RH (%)', fontsize=11, color='k')
    ax.text(285,
            200,
            'CAPE = ' + str(np.around(CAPE.magnitude, decimals=2)) + ' [J/kg]',
            fontsize=12,
            color='green')
    ax.text(285,
            250,
            'CIN = ' + str(np.around(CIN.magnitude, decimals=2)) + ' [J/kg]',
            fontsize=12,
            color='green')
    ax.text(285,
            300,
            'LCL = ' + str(np.around(lcl_pressure.magnitude, decimals=2)) +
            ' [hpa]',
            fontsize=12,
            color='darkorange')
    ax.text(285,
            350,
            'LFC = ' + str(np.around(lfc_pressure.magnitude, decimals=2)) +
            ' [hpa]',
            fontsize=12,
            color='magenta')
    ax.text(285,
            400,
            'CWV = ' + str(np.around(cwv.magnitude, decimals=2)) + ' [mm]',
            fontsize=12,
            color='deepskyblue')
    ax.text(285,
            450,
            'CRH = ' + str(np.around(crh.magnitude, decimals=2)) + ' [%]',
            fontsize=12,
            color='blue')
    ax.legend(['DSE', 'MSE', 'SMSE'], fontsize=12, loc=1)

    ax.set_zorder(3)

    return (ax)
Ejemplo n.º 27
0
a value for vapor pressure assuming both 1000mb and 850mb ambient air
pressure values. It also demonstrates converting the resulting dewpoint
temperature to degrees Fahrenheit.
"""
import metpy.calc as mcalc
from metpy.units import units

###########################################
# Create a test value of mixing ratio in grams per kilogram
mixing = 10 * units('g/kg')
print(mixing)

###########################################
# Now throw that value with units into the function to calculate
# the corresponding vapor pressure, given a surface pressure of 1000 mb
e = mcalc.vapor_pressure(1000. * units.mbar, mixing)
print(e)

###########################################
# Take the odd units and force them to millibars
print(e.to(units.mbar))

###########################################
# Take the raw vapor pressure and throw into the dewpoint function
td = mcalc.dewpoint(e)
print(td)

###########################################
# Which can of course be converted to Fahrenheit
print(td.to('degF'))
Ejemplo n.º 28
0
print('Time length: ', len(time))

# From dimension to variable.
press = np.zeros_like(temp)
for cnt in range(temp.shape[0]):
    press[cnt, :] = lev

pressure = press * units.hPa
temperature = temp * units.K
mixing_ratio = wvmr * units('kg/kg')

# get dew point
relative_humidity = mpcalc.relative_humidity_from_mixing_ratio(
    mixing_ratio, temperature, pressure)
e = mpcalc.vapor_pressure(pressure, mixing_ratio)
dew_point = mpcalc.dewpoint(e)


def get_cape(inargs, return_parcel_profile=False):
    pres_prof, temp_prof, dp_prof = inargs
    try:
        prof = mpcalc.parcel_profile(pres_prof, temp_prof[0], dp_prof[0])
        cape, cin = mpcalc.cape_cin(pres_prof, temp_prof, dp_prof, prof)
    except Exception:
        cape, cin, prof = np.NaN, np.NaN, np.NaN
        print('Problem during CAPE-calculation. Likely NaN-related.')
    if return_parcel_profile:
        return cape, cin, prof
    else:
        return cape, cin
T_NUCAPS = NUCAPS_data.Temperature.values - 273.15
T_NUCAPS = pd.DataFrame({
    'temperature_degC':
    np.reshape(T_NUCAPS, (T_NUCAPS.shape[0] * T_NUCAPS.shape[1]))
})
T_NUCAPS_1 = (NUCAPS_data.Temperature.values - 273.15) * units.degC

H2O_MR = np.reshape(NUCAPS_data['H2O_MR'].values,
                    (T_NUCAPS.shape[0] * T_NUCAPS.shape[1])) * units('g/kg')
H2O_MR_1 = NUCAPS_data['H2O_MR'].values
H2O_MR = pd.DataFrame({'mixing_ratio': H2O_MR})

p_NUCAPS_2 = NUCAPS_data.Pressure.values * units.hPa
WVMR = (H2O_MR_1 * 1000) * units('g/kg')
e_1 = mpcalc.vapor_pressure(p_NUCAPS_2, WVMR)
T_d = mpcalc.dewpoint(e_1)
T_d_NUCAPS = pd.DataFrame({
    'dew_point_degC':
    np.reshape(T_d, (T_NUCAPS.shape[0] * T_NUCAPS.shape[1]))
})

datetime_NUCAPS = NUCAPS_data.datetime.values
datetime_NUCAPS = pd.DataFrame(
    {'time_YMDHMS_1': (np.repeat(datetime_NUCAPS, 100))})

# round datime to next RS time (0000 or 1200)
datetime_NUCAPS_round = pd.DataFrame(
    datetime_NUCAPS.time_YMDHMS_1.dt.ceil('60 min').values,
    columns=['time_YMDHMS'])
datetime_NUCAPS_round.time_YMDHMS[
Ejemplo n.º 30
0
def plotter(fdict):
    """ Go """
    pgconn = get_dbconn("asos")
    ctx = get_autoplot_context(fdict, get_description())

    station = ctx["zstation"]
    month = ctx["month"]

    if month == "all":
        months = range(1, 13)
    elif month == "fall":
        months = [9, 10, 11]
    elif month == "winter":
        months = [12, 1, 2]
    elif month == "spring":
        months = [3, 4, 5]
    elif month == "summer":
        months = [6, 7, 8]
    else:
        ts = datetime.datetime.strptime("2000-" + month + "-01", "%Y-%b-%d")
        # make sure it is length two for the trick below in SQL
        months = [ts.month, 999]

    df = read_sql(
        """
        SELECT drct::int as t, dwpf, tmpf, relh,
        coalesce(mslp, alti * 33.8639, 1013.25) as slp
        from alldata where station = %s
        and drct is not null and dwpf is not null and dwpf <= tmpf
        and sknt > 3 and drct::int %% 10 = 0
        and extract(month from valid) in %s
        and report_type = 2
    """,
        pgconn,
        params=(station, tuple(months)),
    )
    if df.empty:
        raise NoDataFound("No Data Found.")
    # Convert sea level pressure to station pressure
    df["pressure"] = mcalc.add_height_to_pressure(
        df["slp"].values * units("millibars"),
        ctx["_nt"].sts[station]["elevation"] * units("m"),
    ).to(units("millibar"))
    # compute mixing ratio
    df["mixingratio"] = mcalc.mixing_ratio_from_relative_humidity(
        df["relh"].values * units("percent"),
        df["tmpf"].values * units("degF"),
        df["pressure"].values * units("millibars"),
    )
    # compute pressure
    df["vapor_pressure"] = mcalc.vapor_pressure(
        df["pressure"].values * units("millibars"),
        df["mixingratio"].values * units("kg/kg"),
    ).to(units("kPa"))

    means = df.groupby("t").mean().copy()
    # compute dewpoint now
    means["dwpf"] = (mcalc.dewpoint(means["vapor_pressure"].values *
                                    units("kPa")).to(units("degF")).m)

    (fig, ax) = plt.subplots(1, 1)
    ax.bar(
        means.index.values,
        means["dwpf"].values,
        ec="green",
        fc="green",
        width=10,
        align="center",
    )
    ax.grid(True, zorder=11)
    ab = ctx["_nt"].sts[station]["archive_begin"]
    if ab is None:
        raise NoDataFound("Unknown station metadata.")
    ax.set_title(
        ("%s [%s]\nAverage Dew Point by Wind Direction (month=%s) "
         "(%s-%s)\n"
         "(must have 3+ hourly obs > 3 knots at given direction)") % (
             ctx["_nt"].sts[station]["name"],
             station,
             month.upper(),
             max([1973, ab.year]),
             datetime.datetime.now().year,
         ),
        size=10,
    )

    ax.set_ylabel("Dew Point [F]")
    ax.set_ylim(means["dwpf"].min() - 5, means["dwpf"].max() + 5)
    ax.set_xlim(-5, 365)
    ax.set_xticks([0, 45, 90, 135, 180, 225, 270, 315, 360])
    ax.set_xticklabels(["N", "NE", "E", "SE", "S", "SW", "W", "NW", "N"])
    ax.set_xlabel("Wind Direction")

    return fig, means["dwpf"]
Ejemplo n.º 31
0
a value for vapor pressure assuming both 1000mb and 850mb ambient air
pressure values. It also demonstrates converting the resulting dewpoint
temperature to degrees Fahrenheit.
"""
import metpy.calc as mpcalc
from metpy.units import units

###########################################
# Create a test value of mixing ratio in grams per kilogram
mixing = 10 * units('g/kg')
print(mixing)

###########################################
# Now throw that value with units into the function to calculate
# the corresponding vapor pressure, given a surface pressure of 1000 mb
e = mpcalc.vapor_pressure(1000. * units.mbar, mixing)
print(e)

###########################################
# Take the odd units and force them to millibars
print(e.to(units.mbar))

###########################################
# Take the raw vapor pressure and throw into the dewpoint function
td = mpcalc.dewpoint(e)
print(td)

###########################################
# Which can of course be converted to Fahrenheit
print(td.to('degF'))
Ejemplo n.º 32
0
temp = data.variables['air_temperature'][:] * units('degC')
dewp = data.variables['dew_point_temperature'][:] * units('degC')
slp = data.variables['inches_ALTIM'][:] * units('inHg')
wspd = data.variables['wind_speed'][:] * units('m/s')
wdir = data.variables['wind_from_direction'][:] * units('degree')

########################################
# Use MetPy Calculations to calculate RH
# --------------------------------------

# Get ambient partial pressure, use to calculate mixing ratio
es = mpcalc.saturation_vapor_pressure(dewp)
mixr = mpcalc.mixing_ratio(es, slp)

# Calculate vapor pressure
vp = mpcalc.vapor_pressure(slp, mixr)

# Calculate saturation vapor pressure
svp = mpcalc.saturation_vapor_pressure(temp)

# Calculate relative humidity as a percentage
rh = (vp / svp) * 100


########################################
# Make Meteogram Plot
# -------------------

# Create the plots
fig, (ax1, ax2, ax3, ax4) = plt.subplots(4, 1, sharex=True, figsize=(12, 10))
ax1.plot(time, temp, ls='solid', marker='o', color='tab:red', ms=5)
Ejemplo n.º 33
0
df_Temp = pd.DataFrame(T)
df_Temp = df_Temp.loc[[index_CP],:].T
df_Temp.columns = ['FG_Temperature']
df_Temp = df_Temp[0:int(index_min_pressure)]
FG_T_NUCAPS_1 = df_Temp['FG_Temperature'].values -273.15
FG_T_NUCAPS = (df_Temp['FG_Temperature'].values * units.kelvin).to(units.degC)

### MOISTURE
# H2O MR
var = "H2O_MR"
global_scene.load([var], pressure_levels=True)

WVMR = global_scene[var].values # mass mixing ratio (mWV / mDA) kg/kg
WVMR = WVMR * 1000 # convert to grams
WVMR = WVMR * units('g/kg')
e_1 = mpcalc.vapor_pressure(p_NUCAPS_orig, WVMR)
T_d = mpcalc.dewpoint(e_1) 

df_Temp_D = pd.DataFrame(T_d)
df_Temp_D = df_Temp_D.loc[[index_CP],:].T
df_Temp_D.columns = ['Temperature_D']
df_Temp_D = df_Temp_D[0:int(index_min_pressure)]
#T_d_NUCAPS_1 = df_Temp_D['Temperature_D'].values -273.15
T_d_NUCAPS = (df_Temp_D['Temperature_D'].values)

df_Temp_D = pd.DataFrame(T_d.magnitude)
df_Temp_D = df_Temp_D.loc[[index_CP],:].T
df_Temp_D.columns = ['Temperature_D']
df_Temp_D = df_Temp_D[0:int(index_min_pressure)]
#T_d_NUCAPS_1 = df_Temp_D['Temperature_D'].values -273.15
T_d_NUCAPS_1 = (df_Temp_D['Temperature_D'].values)