pythonpointcurve

Find points in curve


Can you share some ideas of how to find curve points (orange color marked places) like shown in picture: enter image description here

I've tried this code:

result = []
    for i in range(len(df)):
        if i == 0 or df['y'].iloc[i] != df['y'].iloc[i - 1]:
            result.append(df.iloc[i])
            continue
        if i < len(df) - 1 and df['y'].iloc[i] != df['y'].iloc[i + 1]:
            result.append(df.iloc[i])

but the problem is, my 'y' isn't always equal between breakpoints and returns too many values. Could you give some advice, how to achieve my goal?

Used data for picture:

time = np.arange(0, 2200, 100)
values = np.array([-0.1, 0, 0.13, 0.27, 0.27, 0.4, 0.27, 0.27, 0.13, 0.13,
                   0.01, 0.01, -0.13, -0.13, -0.27, -0.4, -0.4, -0.27, -0.13, -0.13, 0, 0])

full_time = np.arange(0, 2200, 1)
full_values = np.interp(full_time, time, values)

Solution

  • Here is the full code:

    import numpy as np
    import matplotlib.pyplot as plt
    from scipy.signal import argrelextrema
    
    time = np.arange(0, 2200, 100)
    values = np.array([
        -0.1, 0, 0.13, 0.27, 0.27, 0.4, 0.27, 0.27, 0.13, 0.13,
         0.01, 0.01, -0.13, -0.13, -0.27, -0.4, -0.4, -0.27, -0.13, -0.13, 0, 0
    ])
    
    x = np.arange(0, 2200, 1)
    y = np.interp(x, time, values)
    
    dy = np.gradient(y)
    d2y = np.gradient(dy)
    
    curvature = np.abs(d2y) / (1 + dy**2)**1.5
    
    threshold = 0.0005
    corner_indices = np.where(curvature > threshold)[0]
    
    filtered_corners = [corner_indices[0]]
    for idx in corner_indices[1:]:
        if idx - filtered_corners[-1] > 10:
            filtered_corners.append(idx)
    
    filtered_corners = [0] + filtered_corners + [len(x) - 1]
    filtered_corners = sorted(set(filtered_corners))
    
    plt.figure(figsize=(12, 6))
    plt.plot(x, y, label='Interpolated Curve')
    plt.plot(x[filtered_corners], y[filtered_corners], 'o', color='orange', label='Corners')
    plt.xlabel('x')
    plt.ylabel('y')
    plt.grid(True)
    plt.legend()
    plt.tight_layout()
    plt.show()
    

    Output:

    enter image description here