おおよその開始点が与えられると、この点に最も近い極大値を見つける単純なアルゴリズムを使用できます。あなたの適切なコードはすでにそれを行っている可能性があります(あなたがそれをうまく使っているかどうかはわかりませんでした)。
ユーザーが指定した開始点からの単純なピーク検出を示すコードを次に示します。
#!/usr/bin/env python
from __future__ import division
import numpy as np
from matplotlib import pyplot as plt
# Sample data with two peaks: small one at t=0.4, large one at t=0.8
ts = np.arange(0, 1, 0.01)
xs = np.exp(-((ts-0.4)/0.1)**2) + 2*np.exp(-((ts-0.8)/0.1)**2)
# Say we have an approximate starting point of 0.35
start_point = 0.35
# Nearest index in "ts" to this starting point is...
start_index = np.argmin(np.abs(ts - start_point))
# Find the local maxima in our data by looking for a sign change in
# the first difference
# From http://stackoverflow.com/a/9667121/188535
maxes = (np.diff(np.sign(np.diff(xs))) < 0).nonzero()[0] + 1
# Find which of these peaks is closest to our starting point
index_of_peak = maxes[np.argmin(np.abs(maxes - start_index))]
print "Peak centre at: %.3f" % ts[index_of_peak]
# Quick plot showing the results: blue line is data, green dot is
# starting point, red dot is peak location
plt.plot(ts, xs, '-b')
plt.plot(ts[start_index], xs[start_index], 'og')
plt.plot(ts[index_of_peak], xs[index_of_peak], 'or')
plt.show()
この方法は、ピークへの上昇が開始点から完全にスムーズである場合にのみ機能します。これがノイズに対する耐性を高める必要がある場合、私は使用していませんが、PyDSToolが役立つようです。このSciPy の投稿では、ノイズの多いデータ セットで 1D ピークを検出するために SciPy を使用する方法について詳しく説明しています。
この時点で、ピークの中心を見つけたとします。幅については、使用できる方法がいくつかありますが、最も簡単なのはおそらく「半値全幅」(FWHM) です。繰り返しますが、これは単純であるため脆弱です。2 つのピークが近い場合や、ノイズの多いデータの場合は壊れます。
FWHM はまさにその名前が示すとおりです。ピークの幅が最大値の中間にあることを示します。これを行うコードを次に示します (上記の続きです)。
# FWHM...
half_max = xs[index_of_peak]/2
# This finds where in the data we cross over the halfway point to our peak. Note
# that this is global, so we need an extra step to refine these results to find
# the closest crossovers to our peak.
# Same sign-change-in-first-diff technique as above
hm_left_indices = (np.diff(np.sign(np.diff(np.abs(xs[:index_of_peak] - half_max)))) > 0).nonzero()[0] + 1
# Add "index_of_peak" to result because we cut off the left side of the data!
hm_right_indices = (np.diff(np.sign(np.diff(np.abs(xs[index_of_peak:] - half_max)))) > 0).nonzero()[0] + 1 + index_of_peak
# Find closest half-max index to peak
hm_left_index = hm_left_indices[np.argmin(np.abs(hm_left_indices - index_of_peak))]
hm_right_index = hm_right_indices[np.argmin(np.abs(hm_right_indices - index_of_peak))]
# And the width is...
fwhm = ts[hm_right_index] - ts[hm_left_index]
print "Width: %.3f" % fwhm
# Plot to illustrate FWHM: blue line is data, red circle is peak, red line
# shows FWHM
plt.plot(ts, xs, '-b')
plt.plot(ts[index_of_peak], xs[index_of_peak], 'or')
plt.plot(
[ts[hm_left_index], ts[hm_right_index]],
[xs[hm_left_index], xs[hm_right_index]], '-r')
plt.show()
半値全幅である必要はありません— あるコメンターが指摘しているように、オペレータのピーク検出の通常のしきい値がどこにあるかを把握し、それをプロセスのこのステップのアルゴリズムに変えることができます。
より堅牢な方法は、ガウス曲線 (または独自のモデル) をピークを中心とするデータのサブセットに適合させることです。たとえば、一方の極小値から他方の極小値まで、幅を計算するためのその曲線のパラメーター (例: シグマ)。
これが大量のコードであることは承知していますが、インデックス検索関数を除外して「自分の作業を表示」することは意図的に避けています。
これが少なくとも、特定のセットにより適したものを考え出すための良い出発点になることを願っています.