Рассчитать сдвиг времени между двумя сигналами и сдвиг - PullRequest
0 голосов
/ 17 сентября 2018

У меня есть датчик температуры и датчик деформации, я хотел бы рассчитать задержку между двумя датчиками.

def process_data_time_delay(temperature, strain, normal_data):
    from scipy import signal

    T1 = temperature['T1'].tolist()
    S1 = strain[0]
    time = normal_data['TIMESTAMP'].tolist()

    fig = plt.figure()
    plt.plot(time, T1, 'r')
    plt.plot(time, S1, 'b')

    shift = (np.argmax(signal.correlate(T1, S1)))
    fig  = plt.figure()
    plt.plot(time, T1 - shift)
    plt.show()

У меня странный и странный выходной график.

enter image description here

Вот пример данных

https://pastebin.com/eEd6MTL0

В соответствии с отличным ответом я изменил код для расчета задержкимежду двумя сигналами.

def process_data_time_delay(temperature, strain, df):
    from scipy import signal

    # normalization before ACF
    def normalize(data):
        return (data - np.mean(data, axis=0).reshape((1, -11))) / (np.std(data, axis=0).reshape((1, -1)))

    # select subset of columns, seems relevant as a group
    SCOLS = ['T1', 'W_A1']

    # just to see the data
    f = plt.figure()
    ax = f.add_subplot(111)
    df[SCOLS[:2]].iloc[::10].plot(ax=ax)
    ax.set_title('Raw data')

    # normalization
    normalized = normalize(df[SCOLS].values)
    f = plt.figure()
    ax = f.add_subplot(111)
    ax.plot(np.arange(normalized.shape[0]), normalized[:, 0], label='TW_A1')
    ax.plot(np.arange(normalized.shape[0]), normalized[:, 1], label='W_A1')
    ax.set_title('Normalized')

    # ACF between two components
    x1x2 = np.correlate(normalized[:, 0], normalized[:, 1], 'full')

    # see the results
    f = plt.figure()
    ax = f.add_subplot(111)
    ax.plot(x1x2)
    ax.set_title('ACF')
    df['TIMESTAMP'] = pd.to_datetime(df['TIMESTAMP'])
    peaks_indices = signal.find_peaks_cwt(np.array(x1x2), np.arange(1, len(x1x2)))
    print(peaks_indices)
    delta_index = np.argmax(peaks_indices);
    delta_time = df['TIMESTAMP'][delta_index] - df['TIMESTAMP'][0]
    # assuming timestamps is a datetime64 numpy array that can be easily obtained from pandas;
    shifted_signal = x1x2[delta_time:]

    f = plt.figure()
    ax = f.add_subplot(111)
    ax.plot(shifted_signal)

    # mainloop
    plt.show()

    return x1x2

1 Ответ

0 голосов
/ 17 сентября 2018

Ваш вопрос не о питоне, а об обработке сигналов. Есть много методов и проблем, связанных с оценкой фазы. Например, в периодических сигналах (таких как косинус или прямоугольная волна) есть бесконечные правильные ответы, поскольку реальный сдвиг фазы + целое число периодов даст тот же результат. С другой стороны, даже в непериодических сигналах, таких как один импульс, шум может влиять на обнаружение фазы, в некоторых случаях больше, чем в других. Это широкое поле, и ответ сильно зависит от того, чего вы хотите достичь, и качества данных.

Сказав это, вот мой вывод из ваших данных (двух компонентов) с использованием ACF в качестве первого шага для проверки, я не вижу проблемы с этим:

EDIT:
Добавлены некоторые исправления и изменены сигналы для реальных целей.

ДРУГОЕ РЕДАКТИРОВАНИЕ:

Что касается оценки фазового сдвига, есть много способов сделать это. Пожалуйста, изучите традиционную литературу для ответов и изучите методы, ориентированные на ваш тип данных. Мои предложения:

  1. Первый пик АКФ может быть хорошим ответом.
  2. Проекция на синусоидальные волны (частичные ряды Фурье) и корректировка фазы по наибольшим коэффициентам.
  3. Обнаружение фазы на основе подгонки тех же моделей и проверки параметров (может быть выполнено автоматически, зависит от модели).
  4. Использование детектора огибающей (для этих данных) и определения фаз между двумя верхними и двумя нижними линиями. Вы получите две оценки, вы можете взять среднее.
  5. Используйте больше предварительной обработки - разложение трендов и сезонности, а для проверки фазы берется компонент сезонности.

Есть много способов, они просто появляются сразу. Я уверен, что, немного поиграв с этим, вы сможете найти, что оно подходит вашим данным за разумное время вычислений, поэтому оно будет применимо для вашего продукта.

Удачи!

enter image description here

enter image description here

enter image description here

Вот код:

# just some imports
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

plt.style.use('ggplot')

# load data
df = pd.read_csv('c:\\Temp\\curve_fitting_ahmed.csv')

# normalization before ACF
def normalize(data):
    return (data - np.mean(data, axis=0).reshape((1, -11))) / (np.std(data, axis=0).reshape((1, -1)))


# select subset of columns, seems relevant as a group
SCOLS = ['TW_A1','W_A1']

# just to see the data
f = plt.figure()
ax = f.add_subplot(111)
df[SCOLS[:2]].iloc[::10].plot(ax=ax)
ax.set_title('Raw data')

# normalization
normalized = normalize(df[SCOLS].values)
f = plt.figure()
ax = f.add_subplot(111)
ax.plot(np.arange(normalized.shape[0]),normalized[:,0], label='TW_A1')
ax.plot(np.arange(normalized.shape[0]),normalized[:,1], label='W_A1')
ax.set_title('Normalized')

# ACF between two components
x1x2 = np.correlate(normalized[:, 0], normalized[:, 1], 'full')

# see the results
f = plt.figure()
ax = f.add_subplot(111)
ax.plot(x1x2)
ax.set_title('ACF')

# mainloop
plt.show()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...