Esempio n. 1
0
 def test_ops_wind(self, m_dfp, wind_dataset, tmpdir):
     tmp_weather_path = tmpdir.ensure_dir('operational')
     m_dfp.side_effect = (wind_dataset, )
     wind_avg = wind_tools.calc_wind_avg_at_point(
         arrow.get('2016-02-02 04:25'), str(tmp_weather_path), (0, 0))
     np.testing.assert_allclose(wind_avg.u, 2.5)
     np.testing.assert_allclose(wind_avg.v, -2.5)
Esempio n. 2
0
def _prep_plot_data(grids_15m, tidal_predictions, weather_path):
    max_ssh, max_ssh_time, risk_levels = {}, {}, {}
    u_wind_4h_avg, v_wind_4h_avg, max_wind_avg = {}, {}, {}
    for name in places.TIDE_GAUGE_SITES:
        ssh_ts = nc_tools.ssh_timeseries_at_point(grids_15m[name], 0, 0, datetimes=True)
        ttide = shared.get_tides(name, tidal_predictions)
        max_ssh[name], max_ssh_time[name] = shared.find_ssh_max(name, ssh_ts, ttide)
        risk_levels[name] = stormtools.storm_surge_risk_level(
            name, max_ssh[name], ttide
        )
        wind_avg = wind_tools.calc_wind_avg_at_point(
            arrow.get(max_ssh_time[name]),
            weather_path,
            places.PLACES[name]["wind grid ji"],
            avg_hrs=-4,
        )
        u_wind_4h_avg[name], v_wind_4h_avg[name] = wind_avg
        max_wind_avg[name], _ = wind_tools.wind_speed_dir(
            u_wind_4h_avg[name], v_wind_4h_avg[name]
        )
    plot_data = namedtuple(
        "PlotData",
        "ssh_ts, max_ssh, max_ssh_time, risk_levels, "
        "u_wind_4h_avg, v_wind_4h_avg, max_wind_avg",
    )
    return plot_data(
        ssh_ts,
        max_ssh,
        max_ssh_time,
        risk_levels,
        u_wind_4h_avg,
        v_wind_4h_avg,
        max_wind_avg,
    )
Esempio n. 3
0
 def test_prepend_previous_day(
     self,
     m_dfp,
     wind_dataset,
     tmpdir,
 ):
     tmp_weather_path = tmpdir.ensure_dir('operational')
     wind_prev_day = nc.Dataset('wind_prev_day', 'w')
     wind_prev_day.createDimension('time_counter')
     wind_prev_day.createDimension('y', 1)
     wind_prev_day.createDimension('x', 1)
     u_wind = wind_prev_day.createVariable('u_wind', float,
                                           ('time_counter', 'y', 'x'))
     u_wind[:] = np.arange(5)
     v_wind = wind_prev_day.createVariable('v_wind', float,
                                           ('time_counter', 'y', 'x'))
     v_wind[:] = np.arange(0, -5, -1)
     time_counter = wind_prev_day.createVariable('time_counter', float,
                                                 ('time_counter', ))
     time_counter.time_origin = '2016-FEB-01 00:00:00'
     time_counter[:] = np.arange(19, 24) * 60 * 60
     m_dfp.side_effect = (wind_dataset, wind_prev_day)
     wind_avg = wind_tools.calc_wind_avg_at_point(
         arrow.get('2016-02-02 01:25'), str(tmp_weather_path), (0, 0))
     wind_prev_day.close()
     os.remove('wind_prev_day')
     np.testing.assert_allclose(wind_avg.u, 2)
     np.testing.assert_allclose(wind_avg.v, -2)
def _prep_plot_data(
    place,
    grid_T_hr,
    grids_15m,
    bathy,
    timezone,
    weather_path,
    tidal_predictions,
):
    ssh_hr = grid_T_hr.variables['sossheig']
    time_ssh_hr = nc_tools.timestamp(
        grid_T_hr, range(grid_T_hr.variables['time_counter'].size))
    try:
        j, i = places.PLACES[place]['NEMO grid ji']
    except KeyError as e:
        raise KeyError(f'place name or info key not found in '
                       f'salishsea_tools.places.PLACES: {e}')
    itime_max_ssh = np.argmax(ssh_hr[:, j, i])
    time_max_ssh_hr = time_ssh_hr[itime_max_ssh]
    ssh_15m_ts = nc_tools.ssh_timeseries_at_point(grids_15m[place],
                                                  0,
                                                  0,
                                                  datetimes=True)
    ttide = shared.get_tides(place, tidal_predictions)
    ssh_corr = shared.correct_model_ssh(ssh_15m_ts.ssh, ssh_15m_ts.time, ttide)
    max_ssh_15m, time_max_ssh_15m = shared.find_ssh_max(
        place, ssh_15m_ts, ttide)
    tides_15m = shared.interp_to_model_time(ssh_15m_ts.time, ttide.pred_all,
                                            ttide.time)
    residual = ssh_corr - tides_15m
    max_ssh_residual = residual[ssh_15m_ts.time == time_max_ssh_15m][0]
    wind_4h_avg = wind_tools.calc_wind_avg_at_point(
        arrow.get(time_max_ssh_15m),
        weather_path,
        places.PLACES[place]['wind grid ji'],
        avg_hrs=-4)
    wind_4h_avg = wind_tools.wind_speed_dir(*wind_4h_avg)
    plot_data = namedtuple(
        'PlotData', 'ssh_max_field, time_max_ssh_hr, ssh_15m_ts, ssh_corr, '
        'max_ssh_15m, time_max_ssh_15m, residual, max_ssh_residual, '
        'wind_4h_avg, '
        'ttide, bathy')
    return plot_data(
        ssh_max_field=ssh_hr[itime_max_ssh],
        time_max_ssh_hr=time_max_ssh_hr.to(timezone),
        ssh_15m_ts=ssh_15m_ts,
        ssh_corr=ssh_corr,
        max_ssh_15m=max_ssh_15m - places.PLACES[place]['mean sea lvl'],
        time_max_ssh_15m=arrow.get(time_max_ssh_15m).to(timezone),
        residual=residual,
        max_ssh_residual=max_ssh_residual,
        wind_4h_avg=wind_4h_avg,
        ttide=ttide,
        bathy=bathy,
    )
Esempio n. 5
0
def _calc_wind_4h_avg(feed, max_ssh_time, config):
    weather_path = config["weather"]["ops dir"]
    tide_gauge_stn = config["storm surge feeds"]["feeds"][feed]["tide gauge stn"]
    wind_avg = wind_tools.calc_wind_avg_at_point(
        arrow.get(max_ssh_time),
        weather_path,
        PLACES[tide_gauge_stn]["wind grid ji"],
        avg_hrs=-4,
    )
    wind_vector = wind_tools.wind_speed_dir(wind_avg.u, wind_avg.v)
    return {
        "wind_speed_4h_avg": np.asscalar(wind_vector.speed),
        "wind_dir_4h_avg": np.asscalar(wind_vector.dir),
    }
Esempio n. 6
0
def _calc_wind_4h_avg(feed, max_ssh_time, config):
    weather_path = config['weather']['ops dir']
    tide_gauge_stn = (
        config['storm surge feeds']['feeds'][feed]['tide gauge stn'])
    wind_avg = wind_tools.calc_wind_avg_at_point(
        arrow.get(max_ssh_time),
        weather_path,
        PLACES[tide_gauge_stn]['wind grid ji'],
        avg_hrs=-4)
    wind_vector = wind_tools.wind_speed_dir(wind_avg.u, wind_avg.v)
    return {
        'wind_speed_4h_avg': np.asscalar(wind_vector.speed),
        'wind_dir_4h_avg': np.asscalar(wind_vector.dir),
    }
Esempio n. 7
0
def _prep_plot_data(
    place,
    ssh_fcst_dataset_url_tmpl,
    tidal_predictions,
    forecast_hrs,
    weather_path,
    bathy,
    grid_T_hr_path,
):
    # NEMO sea surface height forecast dataset
    ssh_forecast = _get_ssh_forecast(place, ssh_fcst_dataset_url_tmpl)
    # CHS water level observations dataset
    try:
        obs_1min = (data_tools.get_chs_tides(
            "obs",
            place,
            arrow.get(str(ssh_forecast.time.values[0])) -
            timedelta(seconds=5 * 60),
            arrow.get(str(ssh_forecast.time.values[-1])),
        ).to_xarray().rename({"index": "time"}))
        obs_10min_avg = obs_1min.resample(time="10min", loffset="5min").mean()
        obs = obs_10min_avg.to_dataset(name="water_level")
    except (AttributeError, KeyError):
        # No observations available
        obs = None
    shared.localize_time(ssh_forecast)
    try:
        shared.localize_time(obs)
    except (IndexError, AttributeError):
        # No observations available
        obs = None
    model_ssh_period = slice(str(ssh_forecast.time.values[0]),
                             str(ssh_forecast.time.values[-1]))
    forecast_period = slice(
        str(ssh_forecast.time.values[-forecast_hrs * 6]),
        str(ssh_forecast.time.values[-1]),
    )
    try:
        obs_period = slice(str(obs.time.values[0]), str(obs.time.values[-1]))
    except AttributeError:
        # No observations available
        obs_period = None
    # Predicted tide water levels dataset from ttide
    ttide = shared.get_tides(place, tidal_predictions)
    ttide.rename(columns={" pred_noshallow ": "pred_noshallow"}, inplace=True)
    ttide.index = pandas.to_datetime(ttide.time.values,
                                     format="%Y-%m-%d %H:%M:%S")
    ttide_ds = ttide.to_xarray().drop_vars(["time"]).rename({"index": "time"})
    # Localize ttide dataset timezone to ssh_forecast times because ttide
    # extends well beyond ends of ssh_forecast period
    shared.localize_time(ttide_ds,
                         local_datetime=arrow.get(
                             str(ssh_forecast.time.values[0])).to("local"))
    # NEMO sea surface height dataset corrected to include unmodeled tide constituents
    ssh_correction = ttide_ds.pred_noshallow.sel(
        time=model_ssh_period) - ttide_ds.pred_8.sel(time=model_ssh_period)
    ssh_corrected = ssh_forecast + ssh_correction
    # Mean sea level and extreme water levels
    msl = PLACES[place]["mean sea lvl"]
    extreme_ssh = PLACES[place]["hist max sea lvl"]
    max_tides = ttide.pred_all.max() + msl
    mid_tides = 0.5 * (extreme_ssh - max_tides) + max_tides
    thresholds = (max_tides, mid_tides, extreme_ssh)
    max_ssh = ssh_corrected.ssh.sel(time=forecast_period)
    max_ssh = max_ssh.where(max_ssh == max_ssh.max(), drop=True).squeeze()
    # Residual differences between corrected model and observations and predicted tides
    model_residual = ssh_corrected - ttide_ds.pred_all.sel(
        time=model_ssh_period)
    model_residual.attrs["tz_name"] = ssh_forecast.attrs["tz_name"]
    max_model_residual = model_residual.max()
    try:
        obs_residual = obs - ttide_ds.pred_all.sel(time=obs_period) - msl
        obs_residual.attrs["tz_name"] = obs.attrs["tz_name"]
    except KeyError:
        # No observations available
        obs_residual = None
    # Wind at NEmo model time of max sea surface height
    wind_4h_avg = wind_tools.calc_wind_avg_at_point(
        arrow.get(str(max_ssh.time.values)),
        weather_path,
        PLACES[place]["wind grid ji"],
        avg_hrs=-4,
    )
    wind_4h_avg = wind_tools.wind_speed_dir(*wind_4h_avg)
    # Model sea surface height field for contour map
    tracers_ds = xarray.open_dataset(grid_T_hr_path)
    max_ssh_time_utc = (arrow.get(str(max_ssh.time.values)).replace(
        tzinfo=ssh_forecast.attrs["tz_name"]).to("utc"))
    return SimpleNamespace(
        ssh_forecast=ssh_forecast,
        obs=obs,
        ttide=ttide_ds,
        ssh_corrected=ssh_corrected,
        msl=msl,
        thresholds=thresholds,
        max_ssh=max_ssh,
        model_residual=model_residual,
        max_model_residual=max_model_residual,
        obs_residual=obs_residual,
        wind_4h_avg=wind_4h_avg,
        bathy=bathy,
        max_ssh_field=tracers_ds.sossheig.sel(
            time_counter=max_ssh_time_utc.naive, method="nearest"),
    )