Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
230 views
in Technique[技术] by (71.8m points)

python - Find local max and change of slope points in repeating curve

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). enter image description here

Slope value--> np.diff(Y): enter image description here

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)
Waitting for answers

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...