Example #1
0
    def reader(self, sounding, wdShift=0):
        if (type(sounding) == None):
            logger.error("sounding data empty")
            return

        ## basic variables
        P_released = sounding[self.soundingMeta["P"]][:].to_numpy(dtype=float)
        T_released = sounding[self.soundingMeta["T"]["name"]][:].to_numpy(
            dtype=float)
        Z_released = sounding[self.soundingMeta["Z"]][:].to_numpy(dtype=float)
        RH_released = sounding[self.soundingMeta["RH"]][:].to_numpy(
            dtype=float)
        WS_released = sounding[self.soundingMeta["WS"]["name"]][:].to_numpy(
            dtype=float)
        WD_released = ((sounding[self.soundingMeta["WD"]][:] - wdShift) %
                       360).to_numpy(dtype=float)
        ## metpy cal
        TD_released = mcalc.dewpoint_from_relative_humidity(
            T_released * units(f'{self.soundingMeta["T"]["unit"]}'),
            RH_released / 100).m
        U_released, V_released = mcalc.wind_components(
            WS_released * units(f'{self.soundingMeta["WS"]["unit"]}'),
            WD_released * units.degrees)

        return P_released * units.hPa, T_released * units.degreeC, TD_released * units.degreeC, U_released, V_released
Example #2
0
    def __raw_reader(self, _flist, _file):
        ## customize each instrument
        ## read one file
        with open(pth(self.path, _file),
                  'r',
                  encoding='utf-8',
                  errors='ignore') as f:

            _rename = {
                'airtemp_Avg': 'T',
                'relhumidity_Avg': 'RH',
                'airpressure_Avg': 'P',
                'Wsavg_Avg': 'ws',
                'Wdavg_Avg': 'wd',
                'WindDir_SD1_WVT': 'wd_std'
            }

            _temp = read_csv(f, skiprows=(0, 2, 3), parse_dates=[
                'TIMESTAMP'
            ]).rename(columns=_rename).set_index('TIMESTAMP')

            _temp['Td'] = mcalc.dewpoint_from_relative_humidity(
                _temp['T'].to_numpy(dtype=float) * units.degC,
                _temp['RH'].to_numpy(dtype=float) / 100.).m
            _temp['u'] = -sin(_temp['wd'] / 180. * pi) * _temp['ws']
            _temp['v'] = -cos(_temp['wd'] / 180. * pi) * _temp['ws']

            _flist.append(
                _temp[list(_rename.values()) +
                      ['Td', 'u', 'v']].astype(float).resample('1T').mean())

        return _flist
Example #3
0
 def dew_point(self, level):
     """
     Receives the integer value of the desired vertical pressure level
     to extract from datathe dew point temperature values in degree Celsius.
     It will use previously defined self.temperature() function 
     to extract temperature and use it in a metpy function to obtain dewpoint values.
     In return you will have a np.array for the desired time and level.
     """
     # Obtaining the index for the given pressure level
     index_level = np.where(np.array(self.data["isobaric"]) == level *
                            100)[0][0]
     # Obtain relative humidity data for the given pressure level
     rhum = self.data["Relative_humidity_isobaric"][
         self.time_step][index_level]
     # Assigning units to make metpy function work
     rhum.attrs["units"] = "percent"
     # Obtain air temperature data for the given pressure level
     index_level = np.where(
         np.array(self.data["isobaric6"]) == level * 100)[0][0]
     tair = self.data["Temperature_isobaric"][
         self.time_step][index_level] - 273.15
     # Assigning units to make metpy function work
     tair.attrs["units"] = "degree_Celsius"
     # Calculate dewpoints using a metpy function
     dewp = mpcalc.dewpoint_from_relative_humidity(tair, rhum)
     return np.array(dewp)
    def adjust_data(self, data_with_variables):
        """
        :param data_with_variables: receives the dataframe containing the data and adjust the units
        :return: the updated dataframe
        """
        # converts temperature from Kelvin to Degrees Celsius
        data_with_variables['Temperature_isobaric'] = data_with_variables['Temperature_isobaric'].apply(
            lambda x: x - 273.015)

        # converts pressure from Pa to hPa
        data_with_variables['pressure'] = data_with_variables['pressure'].apply(
            lambda x: x / 100)

        # dictionary with the units used to apply into the mpcalc function
        # the package metpy functions will only deal with data with its units associated
        variables_list = data_with_variables.columns
        variables_units_dict = dict(zip(variables_list, self.units))

        # Attach units to data into the dataframe and return united arrays
        data_with_variables = pandas_dataframe_to_unit_arrays(
            data_with_variables, variables_units_dict)

        # Calculate the ambient dewpoint given air temperature and relative humidity.
        data_with_variables['Dewpoint'] = mpcalc.dewpoint_from_relative_humidity(
            data_with_variables['Temperature_isobaric'],
            data_with_variables['Relative_humidity_isobaric'])

        # converto to pandas dataframe again as the plt_skew() metpy function suggests
        adjusted_data = pd.DataFrame(data_with_variables)
        return adjusted_data
Example #5
0
 def jp_500_t_700_td(self, path):  # 500hPa気温/700hPa湿数(日本域)
     path_fig = os.path.join(path, self.time_str1 + '.jpg')
     if (os.path.exists(path_fig)): return
     # 500hPa気温、緯度、経度の取得
     temp, lat, lon = self.grib2_select_jp('t', 500)
     temp = (temp * units.kelvin).to(units.celsius)
     # 700hPa湿数の取得
     temp_700, _, _ = self.grib2_select_jp('t', 700) * units.kelvin
     rh, _, _ = self.grib2_select_jp('r', 700)
     rh *= 0.01
     dewp_700 = mpcalc.dewpoint_from_relative_humidity(temp_700, rh)
     td = temp_700 - dewp_700
     # 地図の描画
     fig, ax = self.draw_map(self.mapcrs_jp, self.extent_jp)
     # カラーマップを作成する
     N = 256
     M_PuBu = np.flipud(cm.get_cmap('BuPu', N)(range(N)))
     PuBu = ListedColormap(M_PuBu)
     # 等湿数線を引く
     td_constant = ax.contourf(lon,
                               lat,
                               td,
                               np.arange(0, 21, 3),
                               extend='max',
                               cmap=PuBu,
                               transform=self.datacrs,
                               alpha=0.9)
     td_line = ax.contour(lon,
                          lat,
                          td,
                          np.array([-100, 3]),
                          colors='yellow',
                          linestyles='solid',
                          transform=self.datacrs)
     # カラーバーをつける
     cbar = self.draw_jp_colorbar(td_constant)
     cbar.set_label('T-Td($^\circ$C)', fontsize=self.fontsize)
     # 等温線を引く
     temp_line = ax.contour(lon,
                            lat,
                            temp,
                            np.arange(-60, 30, 3),
                            colors='black',
                            linestyles='solid',
                            transform=self.datacrs)
     plt.clabel(temp_line, fontsize=self.fontsize, fmt='%d')
     # タイトルをつける
     self.draw_title(ax, '500hPa: TEMP($^\circ$C)\n700hPa: T-Td($^\circ$C)',
                     self.time_str2)
     # 大きさの調整
     plt.subplots_adjust(bottom=0.05, top=0.95, left=0, right=1.0)
     # 保存
     print(
         f'[{self.time_str2}] 500hPa気温/700hPa湿数(日本域)...{path_fig}'.format())
     plt.savefig(path_fig)
     # 閉じる
     plt.close(fig=fig)
Example #6
0
def add_eqiv_potential_temp(tbs):
    temp = tbs['temp'].values * units.celsius
    rh = tbs['rh'].values * units.percent
    press = tbs['atm_pressure'].values * units.millibar

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

    tbs['dew_point'] = dewpt
    tbs['equiv_potential_temperature'] = np.array(calc.equivalent_potential_temperature(press, temp, dewpt_pint))
    return
Example #7
0
def dewpoint(temp, rel_hum):
    r"""This method calls the metpy.calc function dewpoint_rh
        which takes the pint.Quantity objects containing the
        atmospheric temperature and atmospheric relative
        humidity and produces the dewpoint temperature in units
        of degrees Centigrade.

    """

    q_dewpt = calc.dewpoint_from_relative_humidity(temp, rel_hum)

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

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

    return xr.merge([dset, theta_e])
    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)
Example #10
0
 def calc(self):
     """Compute things not usually computed"""
     if self.data["relh"] is None and None not in [
             self.data["tmpf"],
             self.data["dwpf"],
     ]:
         self.data["relh"] = bounded(
             mcalc.relative_humidity_from_dewpoint(
                 self.data["tmpf"] * munits.degF,
                 self.data["dwpf"] * munits.degF,
             ).to(munits.percent).magnitude,
             0.5,
             100.5,
         )
     if (self.data["dwpf"] is None
             and None not in [self.data["tmpf"], self.data["relh"]]
             and self.data["relh"] >= 1 and self.data["relh"] <= 100):
         self.data["dwpf"] = bounded(
             mcalc.dewpoint_from_relative_humidity(
                 self.data["tmpf"] * munits.degF,
                 self.data["relh"] * munits.percent,
             ).to(munits.degF).magnitude,
             -100.0,
             100.0,
         )
     if self.data["feel"] is None and None not in [
             self.data["tmpf"],
             self.data["relh"],
             self.data["sknt"],
     ]:
         self.data["feel"] = bounded(
             mcalc.apparent_temperature(
                 self.data["tmpf"] * munits.degF,
                 self.data["relh"] * munits.percent,
                 self.data["sknt"] * munits.knots,
             ).to(munits.degF).magnitude,
             -150.0,
             200.0,
         )
Example #11
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
Example #12
0
    def reader(self, sounding=None, wdShift=0):
        if(type(sounding)==None):
            logger.error("sounding data empty")
            return

        ## basic variables
        Time_released = sounding[self.soundingMeta["Time"]]
        P_released    = sounding[self.soundingMeta["P"]][:].to_numpy(dtype=float)
        T_released    = sounding[self.soundingMeta["T"]["name"]][:].to_numpy(dtype=float)
        Z_released    = sounding[self.soundingMeta["Z"]][:].to_numpy(dtype=float)
        RH_released   = sounding[self.soundingMeta["RH"]][:].to_numpy(dtype=float)
        lat_released  = sounding[self.soundingMeta["Lat"]][:].to_numpy(dtype=float)
        lon_released  = sounding[self.soundingMeta["Lon"]][:].to_numpy(dtype=float)
        WS_released   = sounding[self.soundingMeta["WS"]["name"]][:].to_numpy(dtype=float)
        WD_released   = ((sounding[self.soundingMeta["WD"]][:] - wdShift)%360).to_numpy(dtype=float)
        ## metpy cal
        TD_released   = dewpoint_from_relative_humidity(T_released * units(f'{self.soundingMeta["T"]["unit"]}'), RH_released/100).m
        U_released, V_released = wind_components(WS_released * units(f'{self.soundingMeta["WS"]["unit"]}'), WD_released * units.degrees)

        # T, P, T, TD, U, V
        data      = np.asarray([P_released,T_released,Z_released,TD_released,RH_released,U_released.to('m/s').m,V_released.to('m/s').m,lat_released,lon_released])
        dataFrame = DataFrame(np.transpose(data),index=Time_released,columns=['P [hPa]','T [degC]','Z [m]','TD [degC]','RH [%]','U [m/s]','V [m/s]','Lat [o]','Lon [o]'])
        return dataFrame, {'P [hPa]':"hPa", 'T [degC]':"degC", 'Z [m]':'m', 'TD [degC]':"degC", 'RH [%]':"percent", 'U [m/s]':'m/s', 'V [m/s]':'m/s', 'Lat [o]':'deg', 'Lon [o]':'deg'}
Example #13
0
def get_df(network, station, date):
    """Figure out how to get the data being requested."""
    if date == datetime.date.today() and network not in ["ISUSM"]:
        # Use IEM Access
        pgconn = get_dbconn("iem")
        return read_sql(
            "SELECT distinct valid at time zone 'UTC' as utc_valid, "
            "valid at time zone t.tzname as local_valid, tmpf, dwpf, sknt, "
            "drct, vsby, skyc1, skyl1, skyc2, skyl2, skyc3, skyl3, skyc4, "
            "skyl4, relh, feel, alti, mslp, phour, p03i, p24i, "
            "phour as p01i, raw, gust, max_tmpf_6hr, min_tmpf_6hr, "
            "array_to_string(wxcodes, ' ') as wxcodes, snowdepth "
            "from current_log c JOIN stations t on (c.iemid = t.iemid) "
            "WHERE t.id = %s and t.network = %s and "
            "date(valid at time zone t.tzname) = %s ORDER by utc_valid ASC",
            pgconn,
            params=(station, network, date),
            index_col=None,
        )
    nt = NetworkTable(network, only_online=False)
    if station not in nt.sts:
        raise HTTPException(404, "Station + Network unknown to the IEM.")
    tzname = nt.sts[station]["tzname"]
    # This sucks, but alas we want easy datetime construction
    tz = ZoneInfo(tzname)
    sts = datetime.datetime(date.year, date.month, date.day, tzinfo=tz)
    ets = sts + datetime.timedelta(hours=24)
    tz = pytz.timezone(tzname)
    if network.find("_ASOS") > 0:
        # Use ASOS
        pgconn = get_dbconn("asos")
        return read_sql(
            "SELECT valid at time zone 'UTC' as utc_valid, "
            "valid at time zone %s as local_valid, tmpf, dwpf, sknt, drct, "
            "vsby, skyc1, skyl1, skyc2, skyl2, skyc3, skyl3, skyc4, skyl4, "
            "relh, feel, alti, mslp, p01i, p03i, p24i, metar as raw, "
            "p03i, p06i, p24i, max_tmpf_6hr, min_tmpf_6hr, gust, "
            "array_to_string(wxcodes, ' ') as wxcodes, snowdepth "
            "from alldata WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by valid ASC",
            pgconn,
            params=(tzname, station, sts, ets),
            index_col=None,
        )
    if network.find("_RWIS") > 0:
        # Use RWIS
        pgconn = get_dbconn("rwis")
        return read_sql(
            "SELECT valid at time zone 'UTC' as utc_valid, "
            "valid at time zone %s as local_valid, tmpf, dwpf, sknt, drct, "
            "gust from alldata WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by valid ASC",
            pgconn,
            params=(tzname, station, sts, ets),
            index_col=None,
        )
    if network in ["ISUSM", "ISUAG"]:
        # Use ISUAG
        pgconn = get_dbconn("isuag")
        df = read_sql(
            "SELECT valid at time zone 'UTC' as utc_valid, phour, "
            "valid at time zone %s as local_valid, tmpf, relh, sknt, drct "
            "from alldata WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by valid ASC",
            pgconn,
            params=(tzname, station, sts, ets),
            index_col=None,
        )
        # Compute dew point
        if not df.empty:
            try:
                df["dwpf"] = (dewpoint_from_relative_humidity(
                    masked_array(df["tmpf"].values, units("degF")),
                    masked_array(df["relh"].values, units("percent")),
                ).to(units("degF")).m)
            except TypeError:
                df["dwpf"] = np.nan
        return df
    if network == "OT":
        # Use ISUAG
        pgconn = get_dbconn("other")
        return read_sql(
            "SELECT valid at time zone 'UTC' as utc_valid, "
            "valid at time zone %s as local_valid, tmpf, dwpf, sknt, drct "
            "from alldata WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by valid ASC",
            pgconn,
            params=(tzname, station, sts, ets),
            index_col=None,
        )
    if network == "USCRN":
        pgconn = get_dbconn("other")
        df = read_sql(
            "SELECT valid at time zone 'UTC' as utc_valid, "
            "valid at time zone %s as local_valid, tmpc, rh, "
            "wind_mps from uscrn_alldata WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by valid ASC",
            pgconn,
            params=(tzname, station, sts, ets),
            index_col=None,
        )
        if df.empty:
            return df
        # Do some unit work
        tmpc = masked_array(df["tmpc"].values, units("degC"))
        df["tmpf"] = tmpc.to(units("degF")).m
        df["dwpf"] = (dewpoint_from_relative_humidity(
            tmpc, masked_array(df["rh"].values,
                               units("percent"))).to(units("degF")).m)
        df["sknt"] = (masked_array(df["wind_mps"],
                                   units("meters per second")).to(
                                       units("knots")).m)
        return df
    if network.find("_COOP") > 0 or network.find("_DCP") > 0:
        # Use HADS
        pgconn = get_dbconn("hads")
        df = read_sql(
            "SELECT distinct valid at time zone 'UTC' as utc_valid, "
            "key, value "
            f"from raw{date.strftime('%Y')} WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by utc_valid ASC",
            pgconn,
            params=(station, sts, ets),
            index_col=None,
        )
        if df.empty:
            return df
        df = df.pivot_table(index="utc_valid",
                            columns="key",
                            values="value",
                            aggfunc="first")
        df = df.reset_index()
        # Query alldata too as it has the variable conversions done
        df2 = read_sql(
            "SELECT valid at time zone 'UTC' as utc_valid, "
            "tmpf, dwpf, sknt, drct "
            "from alldata WHERE station = %s and "
            "valid >= %s and valid < %s ORDER by utc_valid ASC",
            pgconn,
            params=(station, sts, ets),
            index_col=None,
        )
        df = df.merge(df2, on="utc_valid")

        # Generate the local_valid column
        df["local_valid"] = (df["utc_valid"].dt.tz_localize(
            datetime.timezone.utc).dt.tz_convert(tz))
        return df
    return None
Example #14
0
    for i in range(0, r):
        lon = -startlon - (londelt * i)
        sound_lons.append(lon)

    for i in range(0, 6):
        lat = startlat + lat_delts[i]
        sound_lats.append(lat)
    print(sound_lats)
    for i in range(1, r):
        soundlat = sound_lats[0]
        soundlon = 360 - (startlon + (londelt * i))
        sound_temps = data["temperature"].interp(lat=soundlat, lon=soundlon) - 273.15

        sound_rh = data["rh"].interp(lat=soundlat, lon=soundlon)
        sound_dp = mpcalc.dewpoint_from_relative_humidity(
            sound_temps.data * units.degC, sound_rh.data * units.percent
        )

        skew = SkewT(fig=fig, rect=(0.75 - (0.15 * i), 0.2, 0.15, 0.1))
        skew.plot(sound_pres, sound_dp, "g", linewidth=3)
        skew.plot(sound_pres, sound_temps, "r", linewidth=3)
        skew.ax.axvline(0, color="purple", linestyle="--", linewidth=3)
        skew.ax.set_ylim((1000, ptop))
        skew.ax.axis("off")

    for i in range(0, r):
        soundlat = sound_lats[1]
        soundlon = 360 - (startlon + (londelt * i))
        sound_temps = data["temperature"].interp(lat=soundlat, lon=soundlon) - 273.15

        sound_rh = data["rh"].interp(lat=soundlat, lon=soundlon)
if __name__ == '__main__':

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

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

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

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

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

    #        'dewpoint': dewpoint_rh( (np.array(temp) * units('degC') ).to(units('K') ),
    #                            np.array(rh) / 100.).to(units('degF')),
Example #16
0
    def jp_850_eptw(self, path):  # 850hPa相当温位/風(日本域)

        path_fig = os.path.join(path, self.time_str1 + '.jpg')
        if (os.path.exists(path_fig)): return
        # 850hPa気温の取得
        temp, lat, lon = self.grib2_select_jp('t', 850)
        temp = temp * units.kelvin
        # 850hPa風の取得
        wind_u, _, _ = self.grib2_select_jp('u', 850) * units('m/s')
        wind_v, _, _ = self.grib2_select_jp('v', 850) * units('m/s')
        # 850hPa相対湿度の取得
        rh, _, _ = self.grib2_select_jp('r', 850)
        rh *= 0.01
        # 露点温度の計算
        dewp = mpcalc.dewpoint_from_relative_humidity(temp, rh)
        # 相当温位の計算
        ept = mpcalc.equivalent_potential_temperature(850 * units.hPa, temp,
                                                      dewp)
        ept = gaussian_filter(ept, sigma=1.0)
        # 地図の描画
        fig, ax = self.draw_map(self.mapcrs_jp, self.extent_jp)
        # 等温線を引く
        ept_arange = np.arange(255, 372, 3)
        ept_constant = ax.contourf(lon,
                                   lat,
                                   ept,
                                   ept_arange,
                                   extend='both',
                                   cmap='jet',
                                   transform=self.datacrs,
                                   alpha=0.9)
        ept_line = ax.contour(lon,
                              lat,
                              ept,
                              ept_arange,
                              colors='black',
                              linestyles='solid',
                              linewidths=1,
                              transform=self.datacrs)
        plt.clabel(ept_line,
                   levels=np.arange(258, 372, 6),
                   fmt='%d',
                   fontsize=self.fontsize)
        # カラーバーをつける
        cbar = self.draw_jp_colorbar(ept_constant)
        cbar.set_label('E.P.TEMP(K)', fontsize=self.fontsize)
        # 風ベクトルの表示
        wind_arrow = (slice(None, None, 5), slice(None, None, 5))
        ax.barbs(lon[wind_arrow],
                 lat[wind_arrow],
                 wind_u[wind_arrow].to('kt').m,
                 wind_v[wind_arrow].to('kt').m,
                 pivot='middle',
                 length=8,
                 color='black',
                 alpha=0.5,
                 transform=self.datacrs)
        # タイトルをつける
        self.draw_title(ax, '850hPa: E.P.TEMP(K), WIND ARROW(kt)',
                        self.time_str2)
        # 大きさの調整
        plt.subplots_adjust(bottom=0.05, top=0.95, left=0, right=1.0)
        # 保存
        print(f'[{self.time_str2}] 850hPa相当温位/風(日本域)...{path_fig}'.format())
        plt.savefig(path_fig)
        # 閉じる
        plt.close(fig=fig)
Example #17
0
def plot_soundings(fig,ax,temp,rh,centerlat,centerlon,domainsize,cape):
    '''
    This function will plot a bunch of little soundings onto a matplotlib fig,ax.

    temp is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change the ylimits for other datasets)

    rh is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change )

    centerlat and centerlon are the coordinates around which you want your map
    to be centered. both are floats or integers and are in degrees of latitude
    and degrees of longitude west (i.e. 70W would be input as positive 70 here)

    domainsize is a string either 'local' for ~WFO-size domains or 'regional' for
    NE/SE/Mid-Atlantic-size domains (12 deg lat by 15 deg lon). More will be added soon.

    cape is a boolean to indicate whether you want to overlay parcel paths and
    shade CAPE/CIN on soundings with >100 J/kg of CAPE (this value can be changed)

    note that this function doesn't "return" anything but if you just call it and
    provide the right arguments, it works.

    for example:
        import soundingmaps as smap
        ...
        smap.plot_soundings(fig,ax1,data['temperature'],data['rh'],30.5,87.5,'local',cape=True)

    '''
    r=5
    if domainsize=='local':
        init_lat_delt = 1.625
        init_lon_delt = 0.45
        lat_delts = [.2,.7,1.2,1.75,2.25,2.8]
        londelt = 0.76
        startlon = centerlon-2+0.45

    elif domainsize=='regional':
        init_lat_delt = 6
        init_lon_delt = 1.6
        lat_delts = [0.6,2.5,4.5,6.4,8.4,10.25]
        londelt = 2.9
        startlon = centerlon-7.5+1.6

    startlat = centerlat-init_lat_delt
    startlon = centerlon-2+0.45

    sound_lats=[]
    sound_lons=[]
    for i in range(0,6):
        lats = startlat+lat_delts[i]
        sound_lats.append(lats)

    for i in range(0,r):
        lons = -startlon-(londelt*i)
        sound_lons.append(lons)

    plot_elevs=[0.2,0.3,0.4,0.5,0.6,0.7]

    dashed_red_line = lines.Line2D([], [], linestyle='solid', color='r', label='Temperature')
    dashed_purple_line = lines.Line2D([],[],linestyle='dashed',color='purple',label='0C Isotherm')
    dashed_green_line = lines.Line2D([], [], linestyle='solid', color='g', label='Dew Point')
    grey_line = lines.Line2D([], [], color='darkgray', label='MSLP (hPa)')
    blue_line = lines.Line2D([], [], color='b',label='2m 0C Isotherm')
    pink_line = lines.Line2D([], [], color='fuchsia',label='Surface-Based Parcel Path')
    red = mpatches.Patch(color='tab:red',label='CAPE')
    blue = mpatches.Patch(color='tab:blue',label='CIN')

    if cape==True:
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k==0:
                s=1
            else:
                s=0

            for i in range(s,r):
                sound_pres = temp.lev
                soundlon = -(startlon+(londelt*i))
                sound_temps = temp.interp(lat=soundlat,lon=soundlon)-273.15
                sound_rh = rh.interp(lat=soundlat,lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(sound_temps.data*units.degC,sound_rh.data*units.percent)
                skew = SkewT(fig=fig,rect=(0.75-(0.15*i),plot_elev,.15,.1))

                parcel_prof = mpcalc.parcel_profile(sound_pres,sound_temps[0].data*units.degC,sound_dp[0])
                cape = mpcalc.cape_cin(sound_pres,sound_temps.data*units.degC,sound_dp,parcel_prof)
                capeout = int(cape[0].m)
                cinout = int(cape[1].m)

                skew.plot(sound_pres,sound_dp,'g',linewidth=3)
                skew.plot(sound_pres,sound_temps,'r',linewidth=3)

                if capeout >100:
                    # Shade areas of CAPE and CIN
                    print(sound_temps)
                    print(parcel_prof)
                    skew.shade_cin(sound_pres, sound_temps.data*units.degC, parcel_prof)
                    skew.shade_cape(sound_pres, sound_temps.data*units.degC, parcel_prof)
                    skew.plot(sound_pres,parcel_prof,color='fuchsia',linewidth=1)

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000,300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[dashed_red_line,dashed_green_line,dashed_purple_line,pink_line,red,blue],title='Sounding Legend',loc=4,framealpha=1)

    else:
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k==0:
                s=1
            else:
                s=0

            for i in range(s,r):
                soundlon = -(startlon+(londelt*i))
                sound_pres = temp.lev
                sound_temps = temp.interp(lat=soundlat,lon=soundlon)-273.15
                sound_rh = rh.interp(lat=soundlat,lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(sound_temps.data*units.degC,sound_rh.data*units.percent)
                skew = SkewT(fig=fig,rect=(0.75-(0.15*i),plot_elev,.15,.1))
                skew.plot(sound_pres,sound_dp,'g',linewidth=3)
                skew.plot(sound_pres,sound_temps,'r',linewidth=3)
                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000,300))
                skew.ax.axis('off')
        leg = ax.legend(handles=[dashed_red_line,dashed_green_line,dashed_purple_line],title='Sounding Legend',loc=4,framealpha=1)
Example #18
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))
Example #19
0
rh = testdata['RH']
ws = testdata['WS']
wsmax = testdata['WSMAX']
wd = testdata['WD']
date = testdata['DATE']

# ID For Plotting on Meteogram
probe_id = '0102A'

data = {
    'wind_speed': (np.array(ws) * units('m/s')).to(units('knots')),
    'wind_speed_max': (np.array(wsmax) * units('m/s')).to(units('knots')),
    'wind_direction':
    np.array(wd) * units('degrees'),
    'dewpoint':
    dewpoint_from_relative_humidity((np.array(temp) * units.degC).to(units.K),
                                    np.array(rh) / 100.).to(units('degF')),
    'air_temperature': (np.array(temp) * units('degC')).to(units('degF')),
    'mean_slp':
    calc_mslp(np.array(temp), np.array(pres), hgt_example) * units('hPa'),
    'relative_humidity':
    np.array(rh),
    'times':
    np.array(date)
}

fig = plt.figure(figsize=(20, 16))
add_metpy_logo(fig, 250, 180)
meteogram = Meteogram(fig, data['times'], probe_id)
meteogram.plot_winds(data['wind_speed'], data['wind_direction'],
                     data['wind_speed_max'])
meteogram.plot_thermo(data['air_temperature'], data['dewpoint'])
Example #20
0
def plot_soundings(fig,
                   ax,
                   temp,
                   rh,
                   sfc_pressure,
                   centerlat,
                   centerlon,
                   domainsize,
                   model,
                   cape=False,
                   wetbulb=False):
    """
    This function will plot a bunch of little soundings onto a matplotlib fig,ax.

    temp is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change the ylimits for other datasets)

    rh is an xarray dataarray with temperature data on pressure levels at least
    between 1000 and 300mb (you can change )

    sfc_pressure is an xarray dataarray with surface pressure data (NOT MSLP!)

    centerlat and centerlon are the coordinates around which you want your map
    to be centered. both are floats or integers and are in degrees of latitude
    and degrees of longitude west (i.e. 70W would be input as positive 70 here)

    domainsize is a string either 'local' for ~WFO-size domains or 'regional' for
    NE/SE/Mid-Atlantic-size domains (12 deg lat by 15 deg lon). More will be added soon.

    model is a string that specifies which model is providing data for the plots.
    This determines a few things, most importantly longitude selections. Models
    currently supported are 'GFS','NAM',and 'RAP'

    cape is a boolean to indicate whether you want to overlay parcel paths and
    shade CAPE/CIN on soundings with >100 J/kg of CAPE (this value can be changed)

    wetbulb is a boolean to indicate whether you want to draw wet bulb profiles

    note that this function doesn't "return" anything but if you just call it and
    provide the right arguments, it works.

    for example:
        import soundingmaps as smap
        ...
        smap.plot_soundings(fig,ax1,data['temperature'],data['rh'],30.5,87.5,'local',cape=True)

    """
    r = 5
    if domainsize == "local":
        init_lat_delt = 1.625
        init_lon_delt = 0.45
        lat_delts = [0.2, 0.7, 1.2, 1.75, 2.25, 2.8]
        londelt = 0.76
        startlon = centerlon - 2 + 0.45

    elif domainsize == "regional":
        init_lat_delt = 6
        init_lon_delt = 1.6
        lat_delts = [0.6, 2.5, 4.5, 6.4, 8.4, 10.25]
        londelt = 2.9
        startlon = centerlon - 7.5 + 1.6

    # Lon adjustment for GFS because it's [0,360] not [-180,180]
    if model == 'GFS':
        startlon = 360 - startlon

    # set lat/lon grid from which to pull data to plot soundings
    startlat = centerlat - init_lat_delt

    sound_lats = []
    sound_lons = []
    for i in range(0, 6):
        lats = startlat + lat_delts[i]
        sound_lats.append(lats)

    for i in range(0, r):
        if model == 'GFS':
            lons = startlon - (londelt * i)
        else:
            lons = -startlon - (londelt * i)
        sound_lons.append(lons)

    # this sets how high each row of soundings is on the plot
    plot_elevs = [0.2, 0.3, 0.4, 0.5, 0.6, 0.7]

    # whole bunch of legend stuff
    dashed_red_line = lines.Line2D([], [],
                                   linestyle='solid',
                                   color='r',
                                   label='Temperature')
    dashed_purple_line = lines.Line2D([], [],
                                      linestyle='dashed',
                                      color='purple',
                                      label='0C Isotherm')
    dashed_green_line = lines.Line2D([], [],
                                     linestyle='solid',
                                     color='g',
                                     label='Dew Point')
    grey_line = lines.Line2D([], [], color='darkgray', label='MSLP (hPa)')
    blue_line = lines.Line2D([], [], color='b', label='Wet Bulb')
    pink_line = lines.Line2D([], [],
                             color='fuchsia',
                             label='Surface-Based Parcel Path')
    teal_line = lines.Line2D([], [],
                             linestyle='dashed',
                             color='teal',
                             label='HGZ')
    green_dot = lines.Line2D([], [],
                             marker='o',
                             color='forestgreen',
                             label='LCL')
    black_dot = lines.Line2D([], [],
                             marker='o',
                             color='k',
                             label='Sounding Origin')

    red = mpatches.Patch(color='tab:red', label='CAPE')
    blue = mpatches.Patch(color='tab:blue', label='CIN')

    # do the plotting based on user inputs
    if cape and wetbulb is True:
        print('CAPE + Wetbulb')
        for i, plot_elev in enumerate(plot_elevs):
            soundlat = sound_lats[i]

            if k < 2:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                levs_abv_ground = []
                soundlon = sound_lons[i]
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_pres = temp.lev
                spres = sfc_pressure.interp(lat=soundlat, lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)
                sound_wb = mpcalc.wet_bulb_temperature(
                    sound_pres, sound_temps.data * units.degC, sound_dp)

                #Only want data above the ground
                abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps,
                                                      sound_pres)[0]
                abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp,
                                                      sound_pres)[0]
                abv_sfc_wetb = spt.mask_below_terrain(spres, sound_wb,
                                                      sound_pres)[0]
                pres_abv_ground = spt.mask_below_terrain(
                    spres, sound_temps, sound_pres)[1]

                #sound_wb = sound_wb*units.degC
                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))

                parcel_prof = mpcalc.parcel_profile(
                    pres_abv_ground, abv_sfc_temp[0].data * units.degC,
                    abv_sfc_dewp[0])
                cape = mpcalc.cape_cin(pres_abv_ground,
                                       abv_sfc_temp.data * units.degC,
                                       abv_sfc_dewp, parcel_prof)
                capeout = int(cape[0].m)
                cinout = int(cape[1].m)

                #skew.ax.axvspan(-30, -10, color='cyan', alpha=0.4)

                skew.plot(pres_abv_ground, abv_sfc_wetb, 'b', linewidth=2)
                skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3)
                skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3)

                if capeout > 100:
                    # Shade areas of CAPE and CIN
                    print(pres_abv_ground)
                    print(abv_sfc_temp.data * units.degC)
                    print(parcel_prof)
                    skew.shade_cin(pres_abv_ground,
                                   abv_sfc_temp.data * units.degC, parcel_prof)
                    skew.shade_cape(pres_abv_ground,
                                    abv_sfc_temp.data * units.degC,
                                    parcel_prof)
                    skew.plot(pres_abv_ground,
                              parcel_prof,
                              color='fuchsia',
                              linewidth=1)
                    lcl_pressure, lcl_temperature = mpcalc.lcl(
                        pres_abv_ground[0], abv_sfc_temp.data[0] * units.degC,
                        abv_sfc_dewp[0])
                    skew.plot(lcl_pressure,
                              lcl_temperature,
                              'ko',
                              markerfacecolor='forestgreen')
                    skew.ax.axvline(-30,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)
                    skew.ax.axvline(-10,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)
                skew.plot(975, 0, 'ko', markerfacecolor='k')

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[
            dashed_red_line, dashed_green_line, blue_line, dashed_purple_line,
            teal_line, green_dot, pink_line, red, blue, black_dot
        ],
                        title='Sounding Legend',
                        loc=4,
                        framealpha=1)
    elif cape == True and wetbulb == False:
        print('CAPE no wetbulb')
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k == 0:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                levs_abv_ground = []
                soundlon = sound_lons[i]
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_pres = temp.lev
                spres = sfc_pressure.interp(lat=soundlat, lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)

                abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps,
                                                      sound_pres)[0]
                abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp,
                                                      sound_pres)[0]
                pres_abv_ground = spt.mask_below_terrain(
                    spres, sound_temps, sound_pres)[1]

                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))

                parcel_prof = mpcalc.parcel_profile(
                    pres_abv_ground, abv_sfc_temp[0].data * units.degC,
                    abv_sfc_dewp[0])
                cape = mpcalc.cape_cin(pres_abv_ground,
                                       abv_sfc_temp.data * units.degC,
                                       abv_sfc_dewp, parcel_prof)
                capeout = int(cape[0].m)
                cinout = int(cape[1].m)

                skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3)
                skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3)

                if capeout > 100:
                    # Shade areas of CAPE and CIN
                    skew.shade_cin(pres_abv_ground,
                                   abv_sfc_temp.data * units.degC, parcel_prof)
                    skew.shade_cape(pres_abv_ground,
                                    abv_sfc_temp.data * units.degC,
                                    parcel_prof)
                    skew.plot(pres_abv_ground,
                              parcel_prof,
                              color='fuchsia',
                              linewidth=1)
                    print(abv_sfc_temp)
                    lcl_pressure, lcl_temperature = mpcalc.lcl(
                        pres_abv_ground[0], abv_sfc_temp.data[0] * units.degC,
                        abv_sfc_dewp[0])
                    skew.plot(lcl_pressure,
                              lcl_temperature,
                              'ko',
                              markerfacecolor='forestgreen')
                    skew.ax.axvline(-30,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)
                    skew.ax.axvline(-10,
                                    color='teal',
                                    linestyle='--',
                                    linewidth=1)

                skew.plot(975, 0, 'ko', markerfacecolor='k')

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[
            dashed_red_line, dashed_green_line, dashed_purple_line, teal_line,
            green_dot, pink_line, red, blue, black_dot
        ],
                        title='Sounding Legend',
                        loc=4,
                        framealpha=1)

    elif wetbulb == True and cape == False:
        print('Wetbulb no CAPE')
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k == 0:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                levs_abv_ground = []
                soundlon = sound_lons[i]
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_pres = temp.lev
                spres = sfc_pressure.interp(lat=soundlat, lon=soundlon)

                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)

                sound_wb = mpcalc.wet_bulb_temperature(
                    sound_pres, sound_temps.data * units.degC, sound_dp)

                abv_sfc_temp = spt.mask_below_terrain(spres, sound_temps,
                                                      sound_pres)[0]
                abv_sfc_dewp = spt.mask_below_terrain(spres, sound_dp,
                                                      sound_pres)[0]
                abv_sfc_wetb = spt.mask_below_terrain(spres, sound_wb,
                                                      sound_pres)[0]
                pres_abv_ground = spt.mask_below_terrain(
                    spres, sound_temps, sound_pres)[1]

                #sound_wb = sound_wb*units.degC
                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))

                skew.plot(pres_abv_ground, abv_sfc_wetb, 'b', linewidth=2)
                skew.plot(pres_abv_ground, abv_sfc_dewp, 'g', linewidth=3)
                skew.plot(pres_abv_ground, abv_sfc_temp, 'r', linewidth=3)

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')
    else:
        print('No Wetbulb or CAPE')
        for k in range(len(plot_elevs)):
            soundlat = sound_lats[k]
            plot_elev = plot_elevs[k]

            if k == 0:
                s = 1
            else:
                s = 0

            for i in range(s, r):
                sound_pres = temp.lev
                sound_temps = temp.interp(lat=soundlat, lon=soundlon) - 273.15
                sound_rh = rh.interp(lat=soundlat, lon=soundlon)
                sound_dp = mpcalc.dewpoint_from_relative_humidity(
                    sound_temps.data * units.degC,
                    sound_rh.data * units.percent)
                skew = SkewT(fig=fig,
                             rect=(0.75 - (0.15 * i), plot_elev, .15, .1))
                skew.plot(sound_pres, sound_dp, 'g', linewidth=3)
                skew.plot(sound_pres, sound_temps, 'r', linewidth=3)
                skew.plot(1000, 0, 'ko', markerfacecolor='k')

                skew.ax.axvline(0, color='purple', linestyle='--', linewidth=3)
                skew.ax.set_ylim((1000, 300))
                skew.ax.axis('off')

        leg = ax.legend(handles=[
            dashed_red_line, dashed_green_line, blue_line, dashed_purple_line,
            black_dot
        ],
                        title='Sounding Legend',
                        loc=4,
                        framealpha=1)
Example #21
0
#########################################
##### A) SMN: Surface measurement
#########################################
SMN_data = xr.open_dataset(SMN_archive + '/SMN_concat1.nc').to_dataframe()

SMN_data = SMN_data[SMN_data.time_YMDHMS == int(
    SMN_time.strftime('%Y%m%d%H%M%S'))]
SMN_data = SMN_data[SMN_data.pressure_hPa !=
                    1000]  # delete first row (undefined values)
SMN_data = SMN_data.reset_index(drop=True)

pressure_SMN = SMN_data.pressure_hPa.values * units.hPa
temperature_SMN = SMN_data.temperature_degC.values * units.degC
RH_SMN = SMN_data.relative_humidity_percent.values * units.percent
temperature_d_SMN = cc.dewpoint_from_relative_humidity(temperature_SMN, RH_SMN)
specific_humidity_SMN = cc.specific_humidity_from_dewpoint(
    temperature_d_SMN, pressure_SMN)

##########################################
##### B) RS: RADIOSONDE
##########################################
### read Radiosonde file and save as dataframe ###
RS_data = xr.open_dataset(RS_archive + '/RS_concat.nc').to_dataframe()
#RS_data = pd.read_csv('/data/COALITION2/PicturesSatellite/results_NAL/Radiosondes/RS_20200722000000')
RS_data = RS_data.rename(
    columns={
        'termin': 'time_YMDHMS',
        '744': 'pressure_hPa',
        '745': 'temperature_degC',
        '746': 'relative_humidity_percent',
Example #22
0
def uaPlot(data, level, date, save_dir, ds, td_option):

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

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

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

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

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

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

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

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

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

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

    dpi = plt.rcParams['savefig.dpi'] = 255
    date = date + timedelta(hours=6)
    text = AnchoredText(str(level) + 'mb Wind, Heights, and ' + temps +
                        ' Valid: {0:%Y-%m-%d} {0:%H}:00UTC'.format(date),
                        loc=3,
                        frameon=True,
                        prop=dict(fontsize=22))
    ax.add_artist(text)
    plt.tight_layout()
    save_fname = '{0:%Y%m%d_%H}z_'.format(date) + str(level) + 'mb.pdf'
    plt.savefig(save_dir / save_fname, dpi=dpi, bbox_inches='tight')
Example #23
0
def atmCalc(height, temp, humid):
    print("ATMCALC", height, temp, humid, file=sys.stderr)
    mtny = windh(MTNX, height, ratio=1,
                 yoffset=0)

    windx = XVALUES
    windy = windh(windx, height)

    temp_ = temp * units.degC
    initp = mc.height_to_pressure_std(windy[0] * units.meters)
    dewpt = mc.dewpoint_from_relative_humidity(temp_, humid / 100.)
    lcl_ = mc.lcl(initp, temp_, dewpt, max_iters=50, eps=1e-5)
    LCL = mc.pressure_to_height_std(lcl_[0])

    if (lcl_[0] > mc.height_to_pressure_std(max(windy) * units.meters)
            and LCL > windy[0] * units.meters * 1.000009):
        # add LCL to x
        xlcl = windh(LCL.to('meters').magnitude, height, inv=True)
        windx = np.sort(np.append(windx, xlcl))
        windy = windh(windx, height)

    pressures = mc.height_to_pressure_std(windy * units.meters)

    wvmr0 = mc.mixing_ratio_from_relative_humidity(initp, temp_, humid / 100.)

    # now calculate the air parcel temperatures and RH at each position
    if (lcl_[0] <= min(pressures)):
        T = mc.dry_lapse(pressures, temp_)
        RH = [
            mc.relative_humidity_from_mixing_ratio(
                wvmr0, t, p) for t, p in zip(
                T, pressures)]
    else:
        mini = np.argmin(pressures)
        p1 = pressures[:mini + 1]
        p2 = pressures[mini:]  # with an overlap
        p11 = p1[p1 >= lcl_[0] * .9999999]  # lower (with tol) with lcl
        p12 = p1[p1 < lcl_[0] * 1.000009]  # upper (with tol) with lcl
        T11 = mc.dry_lapse(p11, temp_)
        T12 = mc.moist_lapse(p12, lcl_[1])
        T1 = concatenate((T11[:-1], T12))
        T2 = mc.dry_lapse(p2, T1[-1])
        T = concatenate((T1, T2[1:]))
        wvmrtop = mc.saturation_mixing_ratio(pressures[mini], T[mini])
        RH=[]
        for i in range(len(pressures)):
            if pressures[i] > lcl_[0] and i <= mini:
                v=mc.relative_humidity_from_mixing_ratio(pressures[i], T[i], wvmr0)
            else:
                if i < mini:
                    v=1
                else:
                    v=mc.relative_humidity_from_mixing_ratio(pressures[i], T[i], wvmrtop)
            RH.append(v)
        
        #RH = [mc.relative_humidity_from_mixing_ratio(*tp, wvmr0) if tp[1] > lcl_[
            #0] and i <= mini else 1.0 if i < mini else
            #mc.relative_humidity_from_mixing_ratio(*tp, wvmrtop)
            #for i, tp in enumerate(zip(pressures, T))]

    RH = concatenate(RH)
    return windx, mtny, windy, lcl_, LCL, T.to("degC"), RH
Example #24
0
u_g, v_g = mpcalc.geostrophic_wind(heights)
u_g

#########################################################################
# For profile-based calculations (and most remaining calculations in the ``metpy.calc``
# module), xarray ``DataArray``\s are accepted as inputs, but the outputs remain Pint
# Quantities (typically scalars). Note that MetPy's profile calculations (such as CAPE and
# CIN) require the sounding to be ordered from highest to lowest pressure. As seen earlier
# in this tutorial, this data is ordered the other way, so we need to reverse the inputs
# to ``mpcalc.surface_based_cape_cin``.

data_at_point = data.metpy.sel(time1='2017-09-05 12:00',
                               latitude=30 * units.degrees_north,
                               longitude=260 * units.degrees_east)
dewpoint = mpcalc.dewpoint_from_relative_humidity(
    data_at_point['Temperature_isobaric'],
    data_at_point['Relative_humidity_isobaric'])
cape, cin = mpcalc.surface_based_cape_cin(
    data_at_point['isobaric3'][::-1],
    data_at_point['Temperature_isobaric'][::-1], dewpoint[::-1])
cape

#########################################################################
# A few remaining portions of MetPy's calculations (mainly the interpolation module and a few
# other functions) do not fully support xarray, and so, use of ``.values`` may be needed to
# convert to a bare NumPy array. For full information on xarray support for your function of
# interest, see the :doc:`/api/index`.
#
# CF-Compliant Dataset Example
# ----------------------------
#
Example #25
0
# delta version of the unit.
print(273 * units.kelvin + 10 * units.kelvin)

#########################################################################
print(273 * units.kelvin - 10 * units.kelvin)

#########################################################################
# MetPy Calculations
# ------------------
# All MetPy calculations are unit-aware and rely on this information to ensure
# that the calculations operate correctly. For example, we can use units to take
# an observation in whatever units are most convenient and let MetPy handle everything
# under the hood. Below we calculate dewpoint from the temperature and relative humidity:
temperature = 73.2 * units.degF
rh = 64 * units.percent
dewpoint = mpcalc.dewpoint_from_relative_humidity(temperature, rh)

print(dewpoint)

#########################################################################
# or back to Fahrenheit:
print(dewpoint.to('degF'))

#########################################################################
# Common Mistakes
# ---------------
# There are a few common mistakes the new users often make. Be sure to check
# these when you're having issues.
#
# * Pressure units are `mbar` or `hPa` for common atmospheric measurements. The
#   unit `mb` is actually millibarns--a unit used in particle physics.
Example #26
0
###ax.set_ylabel('{} ({})'.format(temp.standard_name, temp.units))
###ax.set_xlabel('Forecast Time (UTC)')
###ax.grid(True)
###plt.show()

# Calculate wind speed and direction from UV wind
ws = wind_speed(np.array(uwind) * units('m/s'),np.array(vwind) * units('m/s'))
wd = wind_direction(np.array(uwind) * units('m/s'),np.array(vwind) * units('m/s'))

# ID For Plotting on Meteogram
probe_id = '0102A'

ddata = {'wind_speed': (np.array(ws).squeeze() * units('m/s')).to(units('knots')),
        #'wind_speed_max': (np.array(wsmax) * units('m/s')).to(units('knots')),
        'wind_direction': np.array(wd).squeeze() * units('degrees'),
        'dewpoint': dewpoint_from_relative_humidity((np.array(temp).squeeze() * units.K),
                                                    np.array(rh).squeeze() / 100.).to(units('degF')),
        'air_temperature': (np.array(temp).squeeze() * units('K')).to(units('degF')),
        'mean_slp': (np.array(pmsl).squeeze() * units('Pa')).to(units('hPa')),
        #'mean_slp': calc_mslp(np.array(temp), np.array(pres), hgt_example) * units('hPa'),
        'relative_humidity': np.array(rh).squeeze(), 
        'precipitation': np.array(prcip).squeeze(), 
        'times': np.array(time_vals)}

fig = plt.figure(figsize=(20, 16))
add_metpy_logo(fig, 250, 180)
meteogram = Meteogram(fig, ddata['times'], probe_id)
meteogram.plot_winds(ddata['wind_speed'], ddata['wind_direction'],model)
#meteogram.plot_winds(data['wind_speed'], data['wind_direction'], data['wind_speed_max'])
meteogram.plot_thermo(ddata['air_temperature'], ddata['dewpoint'],model)
meteogram.plot_precipitation(ddata['precipitation'],model)
#meteogram.plot_rh(ddata['relative_humidity'])