在多个函数中重复测试 python
repeating tests in multiple functions python
我有一些声音处理功能/声音处理。之前都是单一渠道。但是我知道我会减少或增加多渠道。
此时我有一种感觉,我一遍又一遍地做着一部分的纸条。
在此示例中,它是两个函数(我的原始函数更长),但在单个脚本中也会发生同样的情况。
my Two functions
import numpy as np
# def FFT(x, fs, *args, **kwargs):
def FFT(x, fs, output='complex'):
from scipy.fftpack import fft, fftfreq
N = len(x)
X = fft(x) / N
if output is 'complex':
F = np.linspace(0, N) / (N / fs)
return(F, X, [])
elif output is 'ReIm':
F = np.linspace(0, N) / (N / fs)
RE = np.real(X)
IM = np.imag(X)
return(F, RE, IM)
elif output is 'AmPh0':
F = np.linspace(0, (N-1)/2, N/2)
F = F/(N/fs)
# N should be int becouse of nfft
half_spec = np.int(N / 2)
AMP = abs(X[0:half_spec])
PHI = np.arctan(np.real(X[0:half_spec]) / np.imag(X[0:half_spec]))
return(F, AMP, PHI)
elif output is 'AmPh':
half_spec = np.int(N / 2)
F = np.linspace(1, (N-1)/2, N/2 - 1)
F = F/(N/fs)
AMP = abs(X[1:half_spec])
PHI = np.arctan(np.real(X[1:half_spec])/np.imag(X[1:half_spec]))
return(F, AMP, PHI)
def mFFT(x, fs, spectrum='complex'):
fft_shape = np.shape(x)
if len(fft_shape) == 1:
mF, mX1, mX2 = FFT(x, fs, spectrum)
elif len(fft_shape) == 2:
if fft_shape[0] < fft_shape[1]:
pass
elif fft_shape[0] > fft_shape[1]:
x = x.T
fft_shape = np.shape(x)
mF = mX1 = mX2 = []
for channel in range(fft_shape[0]):
si_mF, si_mX1, si_mX2 = FFT(x[channel], fs, spectrum)
if channel == 0:
mF = np.append(mF, si_mF)
mX1 = np.append(mX1, si_mX1)
mX2 = np.append(mX2, si_mX2)
else:
mF = np.vstack((mF, si_mF))
mX1 = np.vstack((mX1, si_mX1))
if si_mX2 == []:
pass
else:
mX2 = np.vstack((mX2, si_mX2))
elif len(fft_shape) > 2:
raise ValueError("Shape of input can't be greather than 2")
return(mF, mX1, mX2)
本例中的第二个函数有问题。
这个检查的原因最好用一个例子来理解:
我用 4 个麦克风录制了 1 秒的音频数据样本。
所以我有一个 4 x 44100 个样本的 ndim 数组。
FFT 适用于每个偶数长度的数组。这意味着我在两种情况下都得到了结果(4 x 44100 和 44100 x 4)。
对于此函数之后的所有函数,我还有 2 种数据类型。或复杂信号或两个信号(振幅和相位)的元组...在脚本中创建额外开关/检查的内容。
- 检查类型(元组或复杂数据)
- 检查方向(广告更改)
- 检查尺寸/形状
- 运行 函数并追加/堆叠此
是否有一些方法可以减少这种重复我至少有 10 个函数遇到过这种情况...
伯特,
我理解的问题是重复调用您进行各种检查。我不是很了解,但我猜它们是用来格式化您的数据的,您将能够对其执行 fft。
Python 中关于计算机编程的哲学之一是 "It's easier to ask forgiveness than it is to get permission."[1]。这意味着,您可能应该先尝试然后请求宽恕(尝试,除外)。这样做比对值进行大量检查要快得多。此外,那些打算使用你的程序的人应该很容易理解它是如何工作的;通过将逻辑业务与技术逻辑分开,无需这些检查即可轻松阅读。别担心,这并不明显,你问的事实表明你发现的东西不对 :)。
以下是我为您的案例提出的建议(这不是完美的解决方案!):
def mFFT(x, fs, spectrum='complex'):
#Assume we're correcty align when receiving the data
#:param: x assume that we're multi-channel in the format [channel X soundtrack ]
#also, don't do this:
#mF = mX1 = si_mX2 = []
# see why :
mF = []
mX1 = []
mX2 = []
try:
for channel in range(len(x)):
si_mF, si_mX1, si_mX2 = FFT(x[channel], fs, spectrum)
mF.append(si_mF)
mX1.append(si_mX1)
mX2.append(si_mX2)
return (mF, mX1, mX2)
except:
#this is where you would try to point out why it could have failed. One good you had was the check for the orientation of the data and try again;
if np.shape(x)[0] > np.shape(x)[1]:
result = mFFT(x.T,fs,spectrum)
return result
else :
if np.shape(x)[0] > 2:
raise(ValueError("Shape of input isn't supported for greather than 2"))
我举了一个例子,因为我相信你期待一个,但我不会给出完美的答案;)。您遇到的问题是设计问题,不,没有简单的解决方案。我向您建议的是首先假设顺序始终采用这种格式 [第 n 通道 X 样本大小](即 [4 通道 X 44100 样本])。这样,您首先像这样尝试(如 try/except),然后可能以相反的顺序进行尝试。
另一个建议(这实际上取决于您的用例)是创建一个数据结构 class 来将 FFT 数据操纵为 return 复数或 ReIm 或 AmPh0或 AmPh 作为吸气剂。 (因此您将输入数据视为始终是时间,而您只提供用户想要的)。
class FFT(object):
def __init__(self,x, fs):
from scipy.fftpack import fft, fftfreq
self.N = len(x)
self.fs = fs
self.X = fft(x) / N
def get_complex(self):
F = np.linspace(0, self.N) / (self.N / self.fs)
return(F, self.X, [])
def get_ReIm(self):
F = np.linspace(0, self.N) / (self.N / self.fs)
RE,IM = np.real(self.X), np.imag(self.X)
return(F, RE, IM)
def get_AmPh0(self):
F = np.linspace(0, (self.N-1)/2, self.N/2)/(self.N/self.fs)
# N should be int because of nfft
half_spec = np.int(self.N / 2)
AMP = abs(self.X[:half_spec])
PHI = np.arctan(np.real(self.X[:half_spec]) / np.imag(self.X[:half_spec]))
return(F, AMP, PHI)
然后可以根据另一个 class 的所需输出来调用它,并使用 eval 来获得所需的输出(但您需要在代码中使用相同的约定 ;))。 2
我有一些声音处理功能/声音处理。之前都是单一渠道。但是我知道我会减少或增加多渠道。 此时我有一种感觉,我一遍又一遍地做着一部分的纸条。
在此示例中,它是两个函数(我的原始函数更长),但在单个脚本中也会发生同样的情况。
my Two functions
import numpy as np
# def FFT(x, fs, *args, **kwargs):
def FFT(x, fs, output='complex'):
from scipy.fftpack import fft, fftfreq
N = len(x)
X = fft(x) / N
if output is 'complex':
F = np.linspace(0, N) / (N / fs)
return(F, X, [])
elif output is 'ReIm':
F = np.linspace(0, N) / (N / fs)
RE = np.real(X)
IM = np.imag(X)
return(F, RE, IM)
elif output is 'AmPh0':
F = np.linspace(0, (N-1)/2, N/2)
F = F/(N/fs)
# N should be int becouse of nfft
half_spec = np.int(N / 2)
AMP = abs(X[0:half_spec])
PHI = np.arctan(np.real(X[0:half_spec]) / np.imag(X[0:half_spec]))
return(F, AMP, PHI)
elif output is 'AmPh':
half_spec = np.int(N / 2)
F = np.linspace(1, (N-1)/2, N/2 - 1)
F = F/(N/fs)
AMP = abs(X[1:half_spec])
PHI = np.arctan(np.real(X[1:half_spec])/np.imag(X[1:half_spec]))
return(F, AMP, PHI)
def mFFT(x, fs, spectrum='complex'):
fft_shape = np.shape(x)
if len(fft_shape) == 1:
mF, mX1, mX2 = FFT(x, fs, spectrum)
elif len(fft_shape) == 2:
if fft_shape[0] < fft_shape[1]:
pass
elif fft_shape[0] > fft_shape[1]:
x = x.T
fft_shape = np.shape(x)
mF = mX1 = mX2 = []
for channel in range(fft_shape[0]):
si_mF, si_mX1, si_mX2 = FFT(x[channel], fs, spectrum)
if channel == 0:
mF = np.append(mF, si_mF)
mX1 = np.append(mX1, si_mX1)
mX2 = np.append(mX2, si_mX2)
else:
mF = np.vstack((mF, si_mF))
mX1 = np.vstack((mX1, si_mX1))
if si_mX2 == []:
pass
else:
mX2 = np.vstack((mX2, si_mX2))
elif len(fft_shape) > 2:
raise ValueError("Shape of input can't be greather than 2")
return(mF, mX1, mX2)
本例中的第二个函数有问题。
这个检查的原因最好用一个例子来理解:
我用 4 个麦克风录制了 1 秒的音频数据样本。
所以我有一个 4 x 44100 个样本的 ndim 数组。
FFT 适用于每个偶数长度的数组。这意味着我在两种情况下都得到了结果(4 x 44100 和 44100 x 4)。
对于此函数之后的所有函数,我还有 2 种数据类型。或复杂信号或两个信号(振幅和相位)的元组...在脚本中创建额外开关/检查的内容。
- 检查类型(元组或复杂数据)
- 检查方向(广告更改)
- 检查尺寸/形状
- 运行 函数并追加/堆叠此
是否有一些方法可以减少这种重复我至少有 10 个函数遇到过这种情况...
伯特,
我理解的问题是重复调用您进行各种检查。我不是很了解,但我猜它们是用来格式化您的数据的,您将能够对其执行 fft。
Python 中关于计算机编程的哲学之一是 "It's easier to ask forgiveness than it is to get permission."[1]。这意味着,您可能应该先尝试然后请求宽恕(尝试,除外)。这样做比对值进行大量检查要快得多。此外,那些打算使用你的程序的人应该很容易理解它是如何工作的;通过将逻辑业务与技术逻辑分开,无需这些检查即可轻松阅读。别担心,这并不明显,你问的事实表明你发现的东西不对 :)。
以下是我为您的案例提出的建议(这不是完美的解决方案!):
def mFFT(x, fs, spectrum='complex'):
#Assume we're correcty align when receiving the data
#:param: x assume that we're multi-channel in the format [channel X soundtrack ]
#also, don't do this:
#mF = mX1 = si_mX2 = []
# see why :
mF = []
mX1 = []
mX2 = []
try:
for channel in range(len(x)):
si_mF, si_mX1, si_mX2 = FFT(x[channel], fs, spectrum)
mF.append(si_mF)
mX1.append(si_mX1)
mX2.append(si_mX2)
return (mF, mX1, mX2)
except:
#this is where you would try to point out why it could have failed. One good you had was the check for the orientation of the data and try again;
if np.shape(x)[0] > np.shape(x)[1]:
result = mFFT(x.T,fs,spectrum)
return result
else :
if np.shape(x)[0] > 2:
raise(ValueError("Shape of input isn't supported for greather than 2"))
我举了一个例子,因为我相信你期待一个,但我不会给出完美的答案;)。您遇到的问题是设计问题,不,没有简单的解决方案。我向您建议的是首先假设顺序始终采用这种格式 [第 n 通道 X 样本大小](即 [4 通道 X 44100 样本])。这样,您首先像这样尝试(如 try/except),然后可能以相反的顺序进行尝试。
另一个建议(这实际上取决于您的用例)是创建一个数据结构 class 来将 FFT 数据操纵为 return 复数或 ReIm 或 AmPh0或 AmPh 作为吸气剂。 (因此您将输入数据视为始终是时间,而您只提供用户想要的)。
class FFT(object):
def __init__(self,x, fs):
from scipy.fftpack import fft, fftfreq
self.N = len(x)
self.fs = fs
self.X = fft(x) / N
def get_complex(self):
F = np.linspace(0, self.N) / (self.N / self.fs)
return(F, self.X, [])
def get_ReIm(self):
F = np.linspace(0, self.N) / (self.N / self.fs)
RE,IM = np.real(self.X), np.imag(self.X)
return(F, RE, IM)
def get_AmPh0(self):
F = np.linspace(0, (self.N-1)/2, self.N/2)/(self.N/self.fs)
# N should be int because of nfft
half_spec = np.int(self.N / 2)
AMP = abs(self.X[:half_spec])
PHI = np.arctan(np.real(self.X[:half_spec]) / np.imag(self.X[:half_spec]))
return(F, AMP, PHI)
然后可以根据另一个 class 的所需输出来调用它,并使用 eval 来获得所需的输出(但您需要在代码中使用相同的约定 ;))。 2