Example #1
0
def test_persistence_probabilistic_no_data(site_metadata, interval_label,
                                           axis):

    tz = 'UTC'
    interval_length = '5min'
    observation = default_observation(site_metadata,
                                      interval_length=interval_length,
                                      interval_label=interval_label)

    data_start = pd.Timestamp('20190513 1200', tz=tz)
    data_end = pd.Timestamp('20190513 1230', tz=tz)
    closed = datamodel.CLOSED_MAPPING[interval_label]

    data = pd.Series([], index=pd.DatetimeIndex([], tz=tz), dtype=float)
    forecast_start = pd.Timestamp('20190513 1230', tz=tz)
    forecast_end = pd.Timestamp('20190513 1300', tz=tz)
    interval_length = pd.Timedelta('5min')
    load_data = partial(load_data_base, data)

    expected_index = pd.date_range(start=forecast_start,
                                   end=forecast_end,
                                   freq=interval_length,
                                   closed=closed)

    forecasts = persistence.persistence_probabilistic(
        observation, data_start, data_end, forecast_start, forecast_end,
        interval_length, interval_label, load_data, axis, [0.0, 25.0, 50.0])
    assert isinstance(forecasts, list)
    for i, fx in enumerate(forecasts):
        pd.testing.assert_index_equal(fx.index,
                                      expected_index,
                                      check_categorical=False)

        pd.testing.assert_series_equal(
            fx, pd.Series(None, index=expected_index, dtype=float))
Example #2
0
def run_persistence(session,
                    observation,
                    forecast,
                    run_time,
                    issue_time,
                    index=False,
                    load_data=None):
    """
    Run a persistence *forecast* for an *observation*.

    For intraday forecasts, the *index* argument controls if the
    forecast is constructed using persistence of the measured values
    (*index = False*) or persistence using clear sky index or AC power
    index.

    For day ahead forecasts, only persistence of measured values
    (*index = False*) is supported.

    Forecasts may be run operationally or retrospectively. For
    operational forecasts, *run_time* is typically set to now. For
    retrospective forecasts, *run_time* is the time by which the
    forecast should be run so that it could have been be delivered for
    the *issue_time*. Forecasts will only use data with timestamps
    before *run_time*.

    The persistence *window* is the time over which the persistence
    quantity (irradiance, power, clear sky index, or power index) is
    averaged. The persistence window is automatically determined
    from the *forecast* attributes:

    - Intraday persistence forecasts:

      + ``window = forecast.run_length``. No longer than 1 hour.

    - Day ahead forecasts (all but net load) and week ahead forecasts (net
      load only):

      + ``window = forecast.interval_length``.

    Users that would like more flexibility may use the lower-level
    functions in
    :py:mod:`solarforecastarbiter.reference_forecasts.persistence`.

    Parameters
    ----------
    session : api.Session
        The session object to use to request data from the
        SolarForecastArbiter API.
    observation : datamodel.Observation
        The metadata of the observation to be used to create the
        forecast.
    forecast : datamodel.Forecast
        The metadata of the desired forecast.
    run_time : pd.Timestamp
        Run time of the forecast.
    issue_time : pd.Timestamp
        Issue time of the forecast run.
    index : bool, default False
        If False, use persistence of observed value. If True, use
        persistence of clear sky or AC power index.
    load_data : function
        Function to load the observation data 'value' series given
        (observation, data_start, data_end) arguments. Typically,
        calls `session.get_observation_values` and selects the 'value'
        column. May also have data preloaded to then slice from
        data_start to data_end.

    Returns
    -------
    forecast : pd.Series
        Forecast conforms to the metadata specified by the *forecast*
        argument.

    Raises
    ------
    ValueError
        If forecast and issue_time are incompatible.
    ValueError
        If data is required from after run_time.
    ValueError
        If persistence window < observation.interval_length.
    ValueError
        If forecast.run_length => 1 day and index=True.
    ValueError
        If instantaneous forecast and instantaneous observation interval
        lengths do not match.
    ValueError
        If average observations are used to make instantaneous forecast.

    Notes
    -----
    For non-intraday net load forecasts, this function will use a weekahead
    persistence due to the fact that net load exhibits stronger correlation
    week-to-week than day-to-day. For example, the net load on a Monday tends
    to look more similar to the previous Monday that it does to the previous
    day (Sunday).
    """
    utils.check_persistence_compatibility(observation, forecast, index)
    forecast_start, forecast_end = utils.get_forecast_start_end(
        forecast, issue_time, False)
    intraday = utils._is_intraday(forecast)

    if load_data is None:
        load_data = _default_load_data(session)
    data_start, data_end = utils.get_data_start_end(observation, forecast,
                                                    run_time, issue_time)
    if data_end > run_time:
        raise ValueError(
            'Persistence forecast requires data from after run_time')

    if isinstance(forecast, datamodel.ProbabilisticForecast):
        cvs = [f.constant_value for f in forecast.constant_values]
        fx = persistence.persistence_probabilistic(
            observation, data_start, data_end, forecast_start, forecast_end,
            forecast.interval_length, forecast.interval_label, load_data,
            forecast.axis, cvs)
    elif intraday and index:
        fx = persistence.persistence_scalar_index(
            observation, data_start, data_end, forecast_start, forecast_end,
            forecast.interval_length, forecast.interval_label, load_data)
    elif intraday and not index:
        fx = persistence.persistence_scalar(observation, data_start, data_end,
                                            forecast_start, forecast_end,
                                            forecast.interval_length,
                                            forecast.interval_label, load_data)
    elif not intraday and not index:
        fx = persistence.persistence_interval(observation, data_start,
                                              data_end, forecast_start,
                                              forecast.interval_length,
                                              forecast.interval_label,
                                              load_data)
    else:  # pragma: no cover
        raise ValueError(
            'index=True not supported for forecasts with run_length >= 1day')

    return fx