Esempio n. 1
0
def get_neighbourhood_binary(x: np.ndarray,
                             y: np.ndarray,
                             a: int,
                             b: int,
                             t=0.9) -> int:
    """
    Get the index of the point within the range [b, a] where the R2 is close to the threshold.

    This version uses a inaccurate binary search to speedup the search.

    Args:
        x (np.ndarray): the value of the points in the x axis coordinates
        y (np.ndarray): the value of the points in the y axis coordinates
        a (int): the initial point of the search
        b (int): the left limit of the search
        t (float): R2 threshold (default 0.9)

    Returns:
        int: index of the point
    """

    i = b
    right = a

    while abs(i - right) > 1:
        coef = lf.linear_fit(x[i:a + 1], y[i:a + 1])
        r2 = lf.linear_r2(x[i:a + 1], y[i:a + 1], coef)

        if r2 < t:
            i = int((i + right) / 2.0)
        else:
            right = i
            i = int((b + right) / 2.0)

    return i
Esempio n. 2
0
def get_neighbourhood(x: np.ndarray,
                      y: np.ndarray,
                      a: int,
                      b: int,
                      t: float = 0.7) -> tuple:
    """Get the neighbourhood (closest points) from a to b.

    The neighbourhood is defined as the longest straitgh line (defined by R2).

    Args:
        x (np.ndarray): the value of the points in the x axis coordinates
        y (np.ndarray): the value of the points in the y axis coordinates
        a (int): the initial point of the search
        b (int): the left limit of the search
        t (float): R2 threshold

    Returns:
        tuple: (neighbourhood index, r2, slope)
    """

    r2 = 1.0
    i = a - 1
    _, slope = lf.linear_fit(x[i:a + 1], y[i:a + 1])

    while r2 > t and i > b:
        previous_res = (i, r2, slope)
        i -= 1
        coef = lf.linear_fit(x[i:a + 1], y[i:a + 1])
        r2 = lf.linear_r2(x[i:a + 1], y[i:a + 1], coef)
        _, slope = coef

    if r2 > t:
        return i, r2, slope
    else:
        return previous_res
Esempio n. 3
0
def get_neighbourhood_fast(x: np.ndarray,
                           y: np.ndarray,
                           a: int,
                           b: int,
                           t: float = 0.9) -> tuple:
    """
    Get the neighbourhood (closest points) from a to b.

    The neighbourhood is defined as the longest straitgh line (defined by R2).
    This version uses a inaccurate binary search to speedup the search.

    Args:
        x (np.ndarray): the value of the points in the x axis coordinates
        y (np.ndarray): the value of the points in the y axis coordinates
        a (int): the initial point of the search
        b (int): the left limit of the search
        t (float): R2 threshold (default 0.9)

    Returns:
        tuple: (neighbourhood index, r2, slope)
    """
    # speedup when the search using an inaccurate binary search
    i = get_neighbourhood_binary(x, y, a, b, t)
    b, slope = lf.linear_fit(x[i:a + 1], y[i:a + 1])
    r2 = lf.linear_r2(x[i:a + 1], y[i:a + 1], (b, slope))
    previous_res = (i, r2, slope)

    # Linear search to improve accuracy
    while r2 < t and i < a:
        i += 1
        coef = lf.linear_fit(x[i:a + 1], y[i:a + 1])
        r2 = lf.linear_r2(x[i:a + 1], y[i:a + 1], coef)
        _, slope = coef
        previous_res = (i, r2, slope)

    return previous_res
Esempio n. 4
0
def accuracy_trace(points: np.ndarray, knees: np.ndarray) -> tuple:
    """Compute the accuracy heuristic for a set of knees.

    The heuristic is based on the average distance of X and Y axis, the slope and the R2.
    In this version it is used the points from the current knee to the previous.

    Args:
        points (np.ndarray): numpy array with the points (x, y)
        knees (np.ndarray): knees indexes

    Returns:
        tuple: (average_x, average_y, average_slope, average_coeffients, cost)
    """
    x = points[:, 0]
    y = points[:, 1]

    distances_x = []
    distances_y = []
    slopes = []
    coeffients = []

    total_x = math.fabs(x[-1] - x[0])
    total_y = math.fabs(y[-1] - y[0])

    previous_knee_x = x[knees[0]]
    previous_knee_y = y[knees[0]]

    delta_x = x[0] - previous_knee_x
    delta_y = y[0] - previous_knee_y
    distances_x.append(math.fabs(delta_x))
    distances_y.append(math.fabs(delta_y))

    coef = lf.linear_fit(x[0:knees[0] + 1], y[0:knees[0] + 1])
    r2 = lf.linear_r2(x[0:knees[0] + 1], y[0:knees[0] + 1], coef)
    coeffients.append(r2)
    _, slope = coef
    slopes.append(math.fabs(slope))

    for i in range(1, len(knees)):
        knee_x = x[knees[i]]
        knee_y = y[knees[i]]

        delta_x = previous_knee_x - knee_x
        delta_y = previous_knee_y - knee_y

        coef = lf.linear_fit(x[knees[i - 1]:knees[i] + 1],
                             y[knees[i - 1]:knees[i] + 1])
        r2 = lf.linear_r2(x[knees[i - 1]:knees[i] + 1],
                          y[knees[i - 1]:knees[i] + 1], coef)

        distances_x.append(math.fabs(delta_x))
        distances_y.append(math.fabs(delta_y))
        _, slope = coef
        slopes.append(math.fabs(slope))
        coeffients.append(r2)

        previous_knee_x = knee_x
        previous_knee_y = knee_y

    distances_x = np.array(distances_x) / total_x
    distances_y = np.array(distances_y) / total_y
    slopes = np.array(slopes)
    slopes = slopes / slopes.max()

    coeffients = np.array(coeffients)
    coeffients = coeffients / coeffients.max()

    coeffients[coeffients < 0] = 0.0
    p = slopes * distances_y * coeffients
    #p = slopes * distances_y

    average_x = np.average(distances_x)
    average_y = np.average(distances_y)
    average_slope = np.average(slopes)
    average_coeffients = np.average(coeffients)

    cost = average_x / np.average(p)

    return average_x, average_y, average_slope, average_coeffients, cost