1

I have a dataset with x and y values. The curves are plotted and the peaks lie at different values along x-axis.

I am trying to align the peak of all curves using scipy's signal. I tried following this post Use of pandas.shift() to align datasets based on scipy.signal.correlate, but the peaks don't overlap.

import matplotlib.pyplot as plt
from scipy import signal
import math
import numpy as np

a = [0.0002, 0.0005, 0.009, 0.0207, 0.0307, 0.04, 0.044, 0.05, 0.07, 0.07, 0.07, 0.082, 0.087, 0.089, 0.09, 0.09, 0.097,
     0.1, 0.11, 0.149, 0.153, 0.159, 0.16, 0.16, 0.2, 0.24, 0.24, 0.24, 0.25, 0.27, 0.3, 0.385, 0.46, 0.77, 3.7]
b = [0.4, 0.48, 2.2, 2.2, 3.4, 4.0, 4.7, 7.15, 9.9]
c = [0.006, 0.01, 0.01, 0.01, 0.012, 0.013, 0.0178, 0.018, 0.02, 0.022, 0.022, 0.027, 0.031, 0.035, 0.035, 0.036, 0.04,
     0.04, 0.046, 0.046, 0.047, 0.05, 0.0507, 0.06, 0.062, 0.07, 0.071, 0.08, 0.1, 0.143, 0.18, 0.19, 0.255, 0.3, 0.4,
     0.75, 1.25, 4.8, 35.0, 100.0]
d = [0.002, 0.01, 0.012, 0.018, 0.032, 0.035, 0.042, 0.13, 0.14, 0.172]
e = [0.0033, 0.01, 0.012, 0.023, 0.023]

data = {'a': a, 'b': b, 'c': c, 'd': d, 'e': e}

fig = plt.figure()
xc = [*range(0, len(data['c']), 1)]
for k, v in data.items():

    x = [*range(0, len(data[k]), 1)]
    v = [math.log10(i) for i in v]
    # https://stackoverflow.com/questions/10482684/python-reorder-a-sorted-list-so-the-highest-value-is-in-the-middle
    v = v[len(v) % 2::2] + v[::-2]
    # plt.plot(x, [math.log10(i) for i in v], '*')
    if k == 'c':
        plt.plot(xc, v, '*', linestyle='--')
    dx = np.mean(np.diff(xc))
    shift = (np.argmax(signal.correlate(data['c'], v)) - len(v)) * dx
    if k != 'c':
        plt.plot(x + shift, v)

enter image description here

The peaks are not centered around the same value of x. Suggestions on how to do this will be really helpful.

Natasha
  • 1,111
  • 5
  • 28
  • 66

1 Answers1

1
import matplotlib.pyplot as plt
import numpy as np


def centralize(v):
    return np.concatenate((v[len(v) % 2::2], v[::-2]))


def shift_x(v, max_position):
    
    start = max_position - v.argmax()
    end = start + len(v)
    x = np.arange(start, end)
    return x


a = [0.0002, 0.0005, 0.009, 0.0207, 0.0307, 0.04, 0.044, 0.05, 0.07, 0.07, 0.07, 0.082, 0.087, 0.089, 0.09, 0.09, 0.097,
     0.1, 0.11, 0.149, 0.153, 0.159, 0.16, 0.16, 0.2, 0.24, 0.24, 0.24, 0.25, 0.27, 0.3, 0.385, 0.46, 0.77, 3.7]

b = [0.4, 0.48, 2.2, 2.2, 3.4, 4.0, 4.7, 7.15, 9.9]

c = [0.006, 0.01, 0.01, 0.01, 0.012, 0.013, 0.0178, 0.018, 0.02, 0.022, 0.022, 0.027, 0.031, 0.035, 0.035, 0.036, 0.04,
     0.04, 0.046, 0.046, 0.047, 0.05, 0.0507, 0.06, 0.062, 0.07, 0.071, 0.08, 0.1, 0.143, 0.18, 0.19, 0.255, 0.3, 0.4,
     0.75, 1.25, 4.8, 35.0, 100.0]

d = [0.002, 0.01, 0.012, 0.018, 0.032, 0.035, 0.042, 0.13, 0.14, 0.172]

e = [0.0033, 0.01, 0.012, 0.023, 0.023]

data = {'a': a, 'b': b, 'c': c, 'd': d, 'e': e}

fig = plt.figure()

xc = np.arange(len(c))
vc = centralize(np.log10(c))
max_position = vc.argmax()

plt.plot(xc, vc, '*', linestyle='--')
for k, v in data.items():

    if k != 'c':
        v = centralize(np.log10(v))
        x = shift_x(v, max_position)
        plt.plot(x, v)

plt.show()

enter image description here

Joao_PS
  • 633
  • 1
  • 9