'How to synchronize to curves on matplotlib?
I have two curves that have their maximum roughly at the same time, but I'd like to match them exactly.
The first function, maxind
, determines where the maximum is on my temporal list.
The 2nd function, synchro
(where I need help), should synchronize them.
import numpy as np
import matplotlib.pyplot as plt
def generate_examples(shift=+1.0):
# Generate two curves with different maximum
xa = np.linspace(start=0, stop=6, num=1000)
xb = np.linspace(start=0, stop=6, num=2000)
ya = np.sin(xa)
yb = np.sin(xb+shift)**3
return (xa, ya), (xb, yb)
def maxind(T, L):
n = len(L)
M = - np.inf
ind = 0
for i in range(n):
if L[i] > M:
ind = i
M = L[i]
return ind, M, T[ind]
def synchro(xs, ys, TC, XT):
indth, maxth, tth = maxind(xs, ys)
indexp, maxexp, texp = maxind(TC, XT)
L = []
Tsync = []
if indexp < indth:
I = indth - indexp
for i in range(I):
xs.pop(0)
ys.pop(0)
else:
I = indexp - indth
for i in range(I, len(XT)):
L.append(XT[i])
Tsync.append(TC[i])
return Tsync, L
(xa, ya), (xb, yb) = generate_examples(shift=+1.0)
Tsync, L = synchro(ys=xa, xs=ya, XT=xb, TC=yb)
fig, ax = plt.subplots()
ax.plot(xa, ya, color='blue', label='a')
ax.plot(xb, yb, color='red', ls=':', label='b')
ax.plot(L, Tsync, color='red', label='synced')
ax.legend()
I want to put the max of the red curve at the same point in time as the max of the blue curve.
Solution 1:[1]
I tried to construct a working example from the code you provided.
My solution uses numpy
as this makes some things easier, for example you can use directly the argmax
function instead of coding your own maxind
function. See the comments in the code to understand the logic behind calculating the index shift for the curve b.
import numpy as np
import matplotlib.pyplot as plt
def generate_examples(shift=+1.0):
# Generate two curves with different maximum
xa = np.linspace(start=0, stop=6, num=1000)
xb = np.linspace(start=0, stop=6, num=2000)
# note that this is a general case where the two curves have different x values,
# if we assume that they are the same some calculations would become simpler
ya = np.sin(xa)
yb = np.sin(xb+shift)**3 # shift maximum by defined value
return (xa, ya), (xb, yb)
def calculate_shift(xa, ya, xb, yb):
# Get (first) maximum for a and b
iya = np.argmax(ya)
iyb = np.argmax(yb)
# Get the shift in terms of x
dx = xb[iyb] - xa[iya]
print('Shift', dx) # should be roughly +/-1, as we build the examples this way
# Find the shift in xb | find the index of xb which is closest to the shift in x
xb0 = xb - xb[0] # shift xb to ensure it starts with 0
dxb = np.abs(dx) - xb0
ixb = np.argmin(np.abs(dxb))
# returned the signed shift in indices of xb
return int(ixb * np.sign(dx))
def plot(xa, ya, xb, yb,
ixb):
fig, ax = plt.subplots()
ax.plot(xa, ya, color='blue', label='a')
ax.plot(xb, yb, color='red', ls=':', label='b')
if ixb > 0:
ax.plot(xb[:-ixb], yb[ixb:], color='red', label='b - shifted')
else:
ax.plot(xb[-ixb:], yb[:ixb], color='red', label='b - shifted')
ax.legend()
(xa, ya), (xb, yb) = generate_examples(shift=-1.0)
ixb = calculate_shift(xa, ya, xb, yb)
plot(xa, ya, xb, yb, ixb)
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 |