예제 #1
0
def align_intersect_timeseries(base, target):
    """ Align target time series to the base one.
        It assumes a regular time series for the base.
    """
    from vtools.functions.api import interpolate_ts

    if base.interval < target.interval:
        raise ValueError(
            "Untested with coarser target and windowing may be wrong")
    window_common = range_intersect(base, target)
    start = align(window_common[0], base.interval, 1)
    end = align(window_common[1], base.interval, -1)
    base_windowed = base.window(start, end)
    target_aligned = interpolate_ts(target, base_windowed.times, method=LINEAR)
    props = copy.deepcopy(target.props)
    target_aligned._props = props
    return base_windowed, target_aligned
예제 #2
0
def calculate_metrics(tss, lags, interpolate_method='linear'):
    """
    Calculate metrics.

    The first time series is the base, and other are controls.
    The root mean square error is calculated without a lag correction.
    and the shift with the maximum autocorrelation is a lag.
    The other metrics, Bias, NSE, and R are calculated after lag correction
    on controls, which are the second and latter time series.
    """
    assert len(tss) > 1
    ts_base = tss[0]
    metrics = []
    tss_for_scatter = None
    for i in range(len(tss) - 1):
        ts_target = tss[i + 1]
        if ts_base is None or ts_target is None:
            metrics.append(None)
            continue
        window_common = get_common_window((ts_base, ts_target))
        if window_common is None:
            metrics.append(None)
            continue
        ts1 = ts_base.window(*window_common)
        ts2 = ts_target.window(*window_common)
        if np.all(np.isnan(ts1.data)) or np.all(np.isnan(ts2.data)):
            metrics.append(None)
            continue
        if ts1.start != ts2.start or ts1.interval != ts2.interval:
            ts2_interpolated = interpolate_ts(ts_target, ts1,
                                              method=interpolate_method)
            rmse_ = rmse(ts1, ts2_interpolated)
        else:
            ts2_interpolated = ts2
            rmse_ = rmse(ts1, ts2)
        # Items with the lag correction
        if lags[i] is None:
            bias = None
            nse = None
            corr = None
        else:
            if lags[i] != timedelta():
예제 #3
0
def calculate_lag(a,
                  b,
                  max_shift,
                  period=None,
                  resolution=time_interval(minutes=1),
                  interpolate_method=None):
    """ Calculate lag of the second time series b, that maximizes the cross-correlation with a.

        Parameters
        ----------
        a,b: vtools.data.timeseries.Timeseries
            Two time series to compare. The time extent of b must be the same or a superset of that of a.

        max_shift: interval
            Maximum pos/negative time shift to consider in cross-correlation (ie, from -max_shift to +max_shift)

        period: interval, optional
            Period that will be used to further clip the time_window of analysis to fit a periodicity.

        interpolate_method: str, optional
            Interpolate method to generate a time series with a lag-calculation interpolation

        Returns
        -------
        lag : datetime.timedelta
            lag
    """
    # Get the available range from the first time series
    a_windowed_by_b = a.window(b.start, b.end)
    time_window = (a_windowed_by_b.start, a_windowed_by_b.end)
    if (time_window[1] - time_window[0]).total_seconds() <= 0.:
        raise ValueError('No available time series in the given time_window')

    # Calculate actual time range to use
    start = time_window[0] + max_shift
    if period is not None:
        n_periods = np.floor(
            ((time_window[1] - max_shift) - start).total_seconds() /
            period.total_seconds())
        if n_periods <= 0.:
            raise ValueError(
                "The time series is too short to cover one period.")
        end = start + time_interval(seconds=n_periods * period.total_seconds())
    else:
        end = time_window[1] - max_shift
    if (end - start).total_seconds() < 0.:
        raise ValueError("The time series is too short.")

    # This is actual time series to calculate lag
    a_part = a.window(start, end)
    start = a_part.start
    end = a_part.end
    a_part_masked = np.ma.masked_invalid(a_part.data, np.nan)

    # Interpolate the second vector
    factor = a.interval.total_seconds() / resolution.total_seconds()
    if not factor - np.floor(factor) < 1.e-6:
        raise ValueError(
            'The interval of the time series is not integer multiple of the resolution.'
        )
    else:
        factor = int(np.floor(factor))

    new_n = np.ceil((end - start + 2 * max_shift).total_seconds() /
                    resolution.total_seconds()) + 1
    max_shift_tick = int(max_shift.total_seconds() /
                         resolution.total_seconds())
    length = 2 * max_shift_tick + 1
    n = len(a_part)
    if interpolate_method is None:
        interpolate_method = LINEAR
    b_interpolated = interpolate_ts(b,
                                    time_sequence(a_part.start - max_shift,
                                                  resolution, new_n),
                                    method=interpolate_method)

    def unnorm_xcor(lag):
        lag_int = int(lag)
        b_part = b_interpolated.data[lag_int:lag_int + factor * n - 1:factor]
        return -np.ma.inner(a_part_masked, b_part)

    index = np.arange(-max_shift_tick, max_shift_tick + 1)
    brent = True
    if brent is True:
        from scipy.optimize import minimize_scalar
        res = minimize_scalar(unnorm_xcor,
                              method='bounded',
                              bounds=(0, length),
                              options={'xatol': 0.5})
        v0 = index[int(np.floor(res.x))] * resolution.total_seconds()
    else:
        re = np.empty(length)
        for i in range(length):
            re[i] = unnorm_xcor(i)
        v0 = index[np.argmax(-re)] * resolution.total_seconds()
    return time_interval(seconds=v0)
예제 #4
0
        if lags[i] is None:
            bias = None
            nse = None
            corr = None
        else:
            if lags[i] != timedelta():
<<<<<<< HEAD
                ts_target_shifted = shift(ts_target, -lags[i])
=======
                ts_target_shifted = shift(ts_target,-lags[i])
>>>>>>> revisions
                window_common = get_common_window((ts_base, ts_target_shifted))
                ts1 = ts_base.window(*window_common)
                ts2 = ts_target_shifted.window(*window_common)
                if ts1.start != ts2.start or ts1.interval != ts2.interval:
                    ts2_interpolated = interpolate_ts(ts_target_shifted, ts1,
                                                      method=interpolate_method)
                else:
                    ts2_interpolated = ts2
            bias = median_error(ts2_interpolated, ts1)
            nse = skill_score(ts2_interpolated, ts1)
            corr = corr_coefficient(ts2_interpolated, ts1)
        metrics.append({'rmse': rmse_, 'bias': bias,
                        'nse': nse, 'corr': corr, 'lag': lags[i]})
        if i == 0 and lags[0] is not None:
            tss_for_scatter = (ts1, ts2_interpolated)
    return metrics, tss_for_scatter


def set_figure():
    """ Set a Matplotlib figure and return it
    """