【发布时间】:2019-12-12 12:17:14
【问题描述】:
我正在使用拉曼光谱,它通常具有与我感兴趣的实际信息叠加的基线。因此,我想估计基线贡献。为此,我实施了来自this question 的解决方案。
我确实喜欢那里描述的解决方案,并且给出的代码在我的数据上运行良好。计算数据的典型结果如下所示,红色和橙色线是基线估计值:Typical result of baseline estimation with calculated data
问题是:我经常在 pandas DataFrame 中收集数千个光谱,每一行代表一个光谱。我目前的解决方案是使用 for 循环一次遍历一个频谱的数据。然而,这使得该过程相当缓慢。由于我对 python 还比较陌生,并且由于 numpy/pandas/scipy 几乎完全不必使用 for 循环,所以我正在寻找一种解决方案,它也可以省略这个 for 循环。但是,使用的稀疏矩阵函数似乎仅限于二维,但我可能需要三个,而且我还没有想到其他解决方案。有人有想法吗?
当前代码如下所示:
import numpy as np
import pandas as pd
from scipy.signal import gaussian
import matplotlib.pyplot as plt
from scipy import sparse
from scipy.sparse.linalg import spsolve
def baseline_correction(raman_spectra,lam,p,niter=10):
#according to "Asymmetric Least Squares Smoothing" by P. Eilers and H. Boelens
number_of_spectra = raman_spectra.index.size
baseline_data = pd.DataFrame(np.zeros((len(raman_spectra.index),len(raman_spectra.columns))),columns=raman_spectra.columns)
for ii in np.arange(number_of_spectra):
curr_dataset = raman_spectra.iloc[ii,:]
#this is the code for the fitting procedure
L = len(curr_dataset)
w = np.ones(L)
D = sparse.diags([1,-2,1],[0,-1,-2], shape=(L,L-2))
for jj in range(int(niter)):
W = sparse.spdiags(w,0,L,L)
Z = W + lam * D.dot(D.transpose())
z = spsolve(Z,w*curr_dataset.astype(np.float64))
w = p * (curr_dataset > z) + (1-p) * (curr_dataset < z)
#end of fitting procedure
baseline_data.iloc[ii,:] = z
return baseline_data
#the following four lines calculate two sample spectra
wavenumbers = np.linspace(500,2000,100)
intensities1 = 500*gaussian(100,2) + 0.0002*wavenumbers**2
intensities2 = 100*gaussian(100,5) + 0.0001*wavenumbers**2
raman_spectra = pd.DataFrame((intensities1,intensities2),columns=wavenumbers)
#end of smaple spectra calculataion
baseline_data = baseline_correction(raman_spectra,200,0.01)
#the rest is just for plotting the data
plt.figure(1)
plt.plot(wavenumbers,raman_spectra.iloc[0])
plt.plot(wavenumbers,baseline_data.iloc[0])
plt.plot(wavenumbers,raman_spectra.iloc[1])
plt.plot(wavenumbers,baseline_data.iloc[1])
【问题讨论】:
-
raman_spectra.apply(lambda x: baseline_correction(x), axis=1)将执行逐行计算。但是,您必须更新baseline_correction -
Trenton_M,您的建议很有帮助,因为它使代码更短。但是,执行速度几乎相同。在 73 个光谱的测试样本集上,for 循环解决方案大约需要 2.21 秒,而使用应用方法则需要 2.24 秒。因此,我仍在寻找一种速度更快的解决方案,它可以在几秒钟内分析大约 3000 个光谱。
-
您是否尝试过使用 SNIP 进行背景检测?也许它更快。
标签: python scipy signal-processing sparse-matrix baseline