I have an evenly spaced time series (Y) that defines a repeating pattern.
I want to find three kinds of points:
- Red cross: Maximum/Minimum Peaks (highest/lowest points). KNOWN.
- Pink: Local peak/slope change between max peak and min peak.
- Black: Slope change on the peak.
The plot of the time series (Y) in orange. Below it, the slope sign in green (1: positive, 0:negative), and in red the slope of the slope (where the slope changes sign).
Slope value--> np.diff(Y):
Some useful insights i found:
I can get the max/min peaks by using scipy.find_peaks() function.
The data is repeating the same shape yet the points and exact shape are meant to be slightly different as you see. Moreover, there is some noise, especialy near the min peaks.
I have found that my interest points usually have more packed data (diff(y)~0).
How do i find the pink and black points?
Y data is:
Y = np.array([360, 365, 381, 392, 404, 416, 163, 358, 334, 316, 299, 246, 198,
194, 192, 190, 188, 193, 198, 148, 150, 150, 167, 172, 177, 182,
188, 194, 201, 215, 224, 232, 252, 264, 276, 290, 302, 317, 332,
366, 382, 422, 490, 499, 376, 349, 326, 306, 273, 260, 239, 232,
226, 218, 214, 210, 209, 209, 209, 212, 210, 212, 203, 192, 184,
173, 146, 132, 146, 137, 138, 134, 137, 140, 143, 146, 150, 154,
142, 171, 178, 184, 192, 200, 208, 220, 228, 239, 252, 263, 277,
293, 305, 321, 354, 373, 391, 411, 422, 419, 416, 415, 419, 425,
429, 435, 440, 447, 455, 402, 368, 396, 317, 295, 277, 261, 248,
225, 216, 202, 197, 193, 190, 187, 186, 188, 180, 172, 163, 132,
124, 118, 112, 119, 113, 104, 102, 122, 124, 126, 130, 134, 138,
142, 147, 154, 158, 166, 172, 180, 188, 196, 208, 218, 228, 240,
253, 266, 294, 310, 326, 346, 362, 382, 401, 424, 491, 496, 501,
508, 132, 382, 356, 334, 314, 265, 257, 233, 227, 224, 221, 219,
218, 218, 218, 218, 220, 223, 226, 224, 203, 192, 184, 176, 167,
156, 150, 146, 142, 138, 136, 124, 140, 132, 124, 144, 114, 118,
122, 175, 181, 188, 195, 203, 214, 220, 230, 252, 264, 276, 293,
304, 319, 334, 351, 370, 388, 408, 437, 442, 447, 453, 460, 468,
478, 433, 393, 365, 272, 257, 241, 231, 220, 204, 198, 194, 189,
186, 183, 182, 181, 182, 182, 183, 184, 175, 165, 155, 148, 140,
133, 126, 122, 116, 112, 108, 111, 115, 118, 108, 116, 124, 133,
144, 156, 168, 180, 194, 225, 243, 261, 278, 320, 366, 392, 444,
491, 484, 479, 470, 467, 464, 463, 462, 461, 396, 364, 334, 310,
266, 252, 236, 222, 210, 203, 193, 186, 180, 175, 171, 167, 166,
169, 171, 174, 170, 162, 143, 136, 123, 118, 113, 111, 106, 110,
114, 119, 125, 132, 156, 180, 189, 202, 232, 245, 265, 303, 323,
369])
Code to reproduce graphs:
import numpy as np
from matplotlib import pyplot as plt
from scipy.ndimage import median_filter
from scipy.signal import find_peaks
#Get Y values before executing this
#Smooth the curve (reduce noise)
yhat = median_filter(Y, 2)
#Calculate the diff --> yi = y(i+1) - yi
gradient = np.diff(yhat)
#Find peaks (maximum)
max_peaks,_ = find_peaks(yhat, prominence=70 )
min_peaks,_ = find_peaks(-yhat, prominence=70 )
#Plot data and max peak
fig, ax2 = plt.subplots(figsize=(20, 10))
ax2.plot(max_peaks, yhat[max_peaks], "xr",markersize=20)
ax2.plot(min_peaks, yhat[min_peaks], "xr",markersize=20)
ax2.plot(yhat,'-')
ax2.plot(yhat,'o',markersize=4)
#Convert the gradient to binary to see if the slope is negative (0) or positive(1)
gradient2 = np.array([gradient >= 0 ])*100 + 0
ax2.plot(gradient2[0])
#Calculate diff of diff to see where the slope changes
ax2.plot(np.diff(gradient2[0])*0.5)
ax2.set_ylim(-170,600)
ax2.axhline(y=0)
#Plot true value of gradient
fig, ax3 = plt.subplots(figsize=(20, 10))
ax3.plot(gradient)
plt.show()
question from:
https://stackoverflow.com/questions/65906352/find-local-max-and-change-of-slope-points-in-repeating-curve