def detect_regressions(steps, threshold=0):
    """Detect regressions in a (noisy) signal.

    A regression means an upward step in the signal.  The value
    'before' a regression is the value immediately preceding the
    upward step.  The value 'after' a regression is the minimum of
    values after the upward step.

    Parameters
    ----------
    steps : list of (left, right, value, min, error)
        List of steps computed by detect_steps, or equivalent
    threshold : float
        Relative threshold for reporting regressions. Filter out jumps
        whose relative size is smaller than threshold, if they are not
        necessary to explain the difference between the best and the latest
        values.

    Returns
    -------
    latest_value
        Latest value
    best_value
        Best value
    regression_pos : list of (before, after, value_before, value_after)
        List of positions between which the value increased. The first item
        corresponds to the last position at which the best value was obtained.

    """
    if not steps:
        # No data: no regressions
        return None, None, None

    regression_pos = []

    last_v = steps[-1][2]
    best_v = last_v
    best_err = steps[-1][4]
    prev_l = None

    # Find upward steps that resulted to worsened value afterward
    for l, r, cur_v, cur_min, cur_err in reversed(steps):
        if best_v - cur_v > max(cur_err, best_err, threshold * cur_v):
            regression_pos.append((r - 1, prev_l, cur_v, best_v))
        prev_l = l
        if cur_v < best_v:
            best_v = cur_v
            best_err = cur_err

    regression_pos.reverse()

    # Return results
    if regression_pos:
        return (last_v, best_v, regression_pos)
    else:
        return (None, None, None)