我从生物分析仪中得到了一些数据,这些数据可以给我时间(x轴)和吸光度值(y轴)。时间是每0.05秒,从32秒到138秒,因此您可以想象我有多少个数据点。我已经使用plotly和matplotlib创建了一个图形,只是为了让我有更多的库可用于查找解决方案,因此在任何一个库中都可以解决!我想做的是让我的脚本找到每个峰下的面积并返回我的值。
def create_plot(sheet_name):
sample = book.sheet_by_name(sheet_name)
data = [[sample.cell_value(r, c) for r in range(sample.nrows)] for c in range(sample.ncols)]
y = data[2][18:len(data[2]) - 2]
x = np.arange(32, 138.05, 0.05)
indices = peakutils.indexes(y, thres=0.35, min_dist=0.1)
peaks = [y[i] for i in indices]
此代码段获取了我的Y值,X值和峰的索引。现在有没有一种方法可以获取每个曲线下的面积?假设有15个索引。
该图如下所示:
最佳答案
自动答案
给定一组x
和y
值以及一组peaks
(峰的x
坐标),这是如何自动查找每个峰下的面积的方法。我假设x
,y
和peaks
都是Numpy数组:
import numpy as np
# find the minima between each peak
ixpeak = x.searchsorted(peaks)
ixmin = np.array([np.argmin(i) for i in np.split(y, ixpeak)])
ixmin[1:] += ixpeak
mins = x[ixmin]
# split up the x and y values based on those minima
xsplit = np.split(x, ixmin[1:-1])
ysplit = np.split(y, ixmin[1:-1])
# find the areas under each peak
areas = [np.trapz(ys, xs) for xs,ys in zip(xsplit, ysplit)]
输出:
已设置示例数据,以确保(或多或少)每个峰下的面积为
1.0
,因此底部图中的结果是正确的。绿色的X标记是每两个峰之间最小值的位置。将“属于”每个峰的曲线部分确定为与每个峰相邻的最小值之间的曲线部分。完整的代码
这是我用来生成示例数据的完整代码:
import scipy as sp
import scipy.stats
prec = 1e5
n = 10
N = 150
r = np.arange(0, N+1, N//n)
# generate some reasonable fake data
peaks = np.array([np.random.uniform(s, e) for s,e in zip(r[:-1], r[1:])])
x = np.linspace(0, N + n, num=int(prec))
y = np.max([sp.stats.norm.pdf(x, loc=p, scale=.4) for p in peaks], axis=0)
以及我用来绘制曲线的代码:
import matplotlib.pyplot as plt
# plotting stuff
plt.figure(figsize=(5,7))
plt.subplots_adjust(hspace=.33)
plt.subplot(211)
plt.plot(x, y, label='trace 0')
plt.plot(peaks, y[ixpeak], '+', c='red', ms=10, label='peaks')
plt.plot(mins, y[ixmin], 'x', c='green', ms=10, label='mins')
plt.xlabel('dep')
plt.ylabel('indep')
plt.title('Example data')
plt.ylim(-.1, 1.6)
plt.legend()
plt.subplot(212)
plt.bar(np.arange(len(areas)), areas)
plt.xlabel('Peak number')
plt.ylabel('Area under peak')
plt.title('Area under the peaks of trace 0')
plt.show()