10

デジタル出力を表す CSV 値の配列があります。アナログオシロスコープを使用して収集されているため、完全なデジタル信号ではありません。期間を計算するための完全なデジタル信号を得るためにデータを除外しようとしています (これは異なる場合があります)。また、このフィルタリングから得られる最大エラーを定義したいと思います。

このようなもの:

ここに画像の説明を入力

考え

データにしきい値を適用します。擬似コードは次のとおりです。

for data_point_raw in data_array:
    if data_point_raw < 0.8: data_point_perfect = LOW
    if data_point_raw > 2  : data_point_perfect = HIGH

else:
    #area between thresholds
    if previous_data_point_perfect == Low : data_point_perfect = LOW
    if previous_data_point_perfect == HIGH: data_point_perfect = HIGH

私を悩ませている2つの問題があります。

  1. これはデジタル信号処理の一般的な問題のようですが、定義済みの標準関数は見つかりませんでした。これは、フィルタリングを実行するための適切な方法ですか?
  2. どうすれば最大誤差を取得できますか?
4

4 に答える 4

7

ここに役立つかもしれないコードが少しあります。

from __future__ import division

import numpy as np


def find_transition_times(t, y, threshold):
    """
    Given the input signal `y` with samples at times `t`,
    find the times where `y` increases through the value `threshold`.

    `t` and `y` must be 1-D numpy arrays.

    Linear interpolation is used to estimate the time `t` between
    samples at which the transitions occur.
    """
    # Find where y crosses the threshold (increasing).
    lower = y < threshold
    higher = y >= threshold
    transition_indices = np.where(lower[:-1] & higher[1:])[0]

    # Linearly interpolate the time values where the transition occurs.
    t0 = t[transition_indices]
    t1 = t[transition_indices + 1]
    y0 = y[transition_indices]
    y1 = y[transition_indices + 1]
    slope = (y1 - y0) / (t1 - t0)
    transition_times = t0 + (threshold - y0) / slope

    return transition_times


def periods(t, y, threshold):
    """
    Given the input signal `y` with samples at times `t`,
    find the time periods between the times at which the
    signal `y` increases through the value `threshold`.

    `t` and `y` must be 1-D numpy arrays.
    """
    transition_times = find_transition_times(t, y, threshold)
    deltas = np.diff(transition_times)
    return deltas


if __name__ == "__main__":
    import matplotlib.pyplot as plt

    # Time samples
    t = np.linspace(0, 50, 501)
    # Use a noisy time to generate a noisy y.
    tn = t + 0.05 * np.random.rand(t.size)
    y = 0.6 * ( 1 + np.sin(tn) + (1./3) * np.sin(3*tn) + (1./5) * np.sin(5*tn) +
               (1./7) * np.sin(7*tn) + (1./9) * np.sin(9*tn))

    threshold = 0.5
    deltas = periods(t, y, threshold)
    print("Measured periods at threshold %g:" % threshold)
    print(deltas)
    print("Min:  %.5g" % deltas.min())
    print("Max:  %.5g" % deltas.max())
    print("Mean: %.5g" % deltas.mean())
    print("Std dev: %.5g" % deltas.std())

    trans_times = find_transition_times(t, y, threshold)

    plt.plot(t, y)
    plt.plot(trans_times, threshold * np.ones_like(trans_times), 'ro-')
    plt.show()

出力:

Measured periods at threshold 0.5:
[ 6.29283207  6.29118893  6.27425846  6.29580066  6.28310224  6.30335003]
Min:  6.2743
Max:  6.3034
Mean: 6.2901
Std dev: 0.0092793

プロット

numpy.histogramand/orを使用しmatplotlib.pyplot.histて、 によって返された配列をさらに分析できますperiods(t, y, threshold)

于 2013-02-27T14:46:44.897 に答える
2

これはあなたの質問に対する答えではなく、役立つかもしれない提案です。コメントに画像を入れることができないので、ここに書いています。

処理の前に、何らかの方法でデータを正規化する必要があると思います。

0...1 の範囲に正規化した後、フィルタを適用する必要があります。

ここに画像の説明を入力

于 2013-02-27T14:36:47.293 に答える
1

本当に周期にのみ関心がある場合は、フーリエ変換をプロットすると、信号の周波数が発生するピークが得られます(したがって、周期があります)。フーリエ領域のピークが広いほど、周期測定の誤差が大きくなります

import numpy as np

data = np.asarray(my_data)

np.fft.fft(data)
于 2013-02-27T13:17:41.450 に答える
1

フィルタリングは問題ありません。基本的にはシュミットトリガーと同じですが、主な問題は速度です。Numpy を使用する利点は、各要素を 1 回反復する必要があるのに対し、C と同じくらい高速になることです。

SciPy のメディアン フィルターを使用して、同様のことを実現できます。以下は同様の結果を達成するはずです(大きさに依存しません):

filtered = scipy.signal.medfilt(raw)
filtered = numpy.where(filtered > numpy.mean(filtered), 1, 0)

でメディアン フィルタリングの強度を調整できますmedfilt(raw, n_samples)n_samplesデフォルトは 3 です。

エラーに関しては、それは非常に主観的なものになります。1 つの方法は、フィルター処理を行わずに信号を離散化し、差を比較することです。例えば:

discrete = numpy.where(raw > numpy.mean(raw), 1, 0)
errors = np.count_nonzero(filtered != discrete)
error_rate = errors / len(discrete)
于 2013-02-27T14:23:21.343 に答える