Python 单周期傅里叶窗口优化。我的代码效率很低

Python 单周期傅里叶窗口优化。我的代码效率很低,python,signal-processing,simpowersystems,Python,Signal Processing,Simpowersystems,你好 编辑: 我想要的:从电力系统(PS)上的任何电流/电压波形中,我想要过滤的50Hz(基本)RMS值大小(以及它们的角度)。根据设备的不同,测量的电流包含从100Hz到1250Hz的所有谐波。人们无法使用含有这些谐波的波进行分析和计算,因为误差太大(取决于设备),以致PS保护设备计算出的量不正确。附加的信号还涉及许多其他频率分量 我的目标:PS保护继电器非常特殊,可以在很短的时间内计算出20毫秒的窗口。我不想得到这个。我正在使用外部记录技术,测试继电器所看到的是真实的,它们工作正常。因此,我

你好

编辑: 我想要的:从电力系统(PS)上的任何电流/电压波形中,我想要过滤的50Hz(基本)RMS值大小(以及它们的角度)。根据设备的不同,测量的电流包含从100Hz到1250Hz的所有谐波。人们无法使用含有这些谐波的波进行分析和计算,因为误差太大(取决于设备),以致PS保护设备计算出的量不正确。附加的信号还涉及许多其他频率分量

我的目标:PS保护继电器非常特殊,可以在很短的时间内计算出20毫秒的窗口。我不想得到这个。我正在使用外部记录技术,测试继电器所看到的是真实的,它们工作正常。因此,我需要做他们所做的,只保持50Hz值,没有任何谐波和直流电

重要预期结果:给定信号中可能存在的任何频率分量,我希望看到任何给定谐波的幅值(150250-基波的三次谐波幅值和五次谐波)以及直流的幅值。这将告诉我什么类型的PS设备可能注入这些频率。重要的是,我提供了一个频率,答案是该频率的向量,只有过滤掉所有其他值。 基本频率的RMS与RMS的差异系数为4000A(仅50Hz)和4500A(包括其他频率)

该代码计算给定频率的单周期傅里叶值(RMS)。我想有时被称为傅里叶滤波器?我将其用于电力系统50Hz/0Hz/150Hz模拟分析。(答案经过测试,是正确的基本RMS值。()

对于一个大样本,代码非常慢。对于55000个数据点,它需要12秒。对于3个电压和3个电流,这非常慢。我每天查看100个记录

如何增强它?有哪些Python提示和技巧/库附加我的列表/数组。 (也可以随意重写或使用代码)。我使用代码在给定时间从信号中提取特定值。(这就像从电力系统分析专用程序中读取值一样) 编辑:根据我加载和使用文件的方式,代码可以粘贴文件:

粘贴的代码在附加文件的情况下运行平稳 问候

编辑:请在此处找到测试csvfile和COMTRADE测试文件: CSV:

COMTRADE

前言 正如我在之前的评论中所说:

您的代码主要依赖于带有大量索引和 标量操作。您已经导入了
numpy
,因此应该 矢量化的优点

这个答案是你解决问题的开始

轻质MCVE 首先,我们为MCVE创建一个试验信号:

import numpy as np

# Synthetic signal sampler: 5s sampled as 400 Hz
fs = 400 # Hz
t = 5    # s
t = np.linspace(0, t, fs*t+1)

# Synthetic Signal: Amplitude is about 325V @50Hz
A = 325 # V
f = 50  # Hz
y = A*np.sin(2*f*np.pi*t) # V
然后,我们可以使用通常的公式计算该信号的频率:

# Actual definition of RMS:
yrms = np.sqrt(np.mean(y**2)) # 229.75 V
或者,我们也可以使用(在
numpy.fft
中实现)计算它:

我们可以找到最后一个公式的工作原理,这是有效的,因为傅里叶变换确实节约了能量

两种版本都使用矢量化函数,不需要拆分实部和虚部来执行计算,然后重新组合成复数

MCVE:窗口化 我怀疑您想将此函数用作RMS值即将更改的长期时间序列的窗口。然后,我们可以使用提供时间序列商品的
pandas
库来解决此问题

import pandas as pd
我们封装了RMS函数:

def rms(y):
    Y = 2*np.fft.rfft(y)/y.size
    return np.sqrt(np.real(Y[0]**2 + np.sum(Y[1:]*np.conj(Y[1:]))/2))
我们生成一个阻尼信号(可变RMS)

我们将试验信号包装到数据帧中,以利用
滚动
重采样
方法:

df = pd.DataFrame(y, index=t*pd.Timedelta('1s'), columns=['signal'])
信号的滚动RMS为:

df['rms'] = df.rolling(int(fs/f)).agg(rms)
周期性采样的RMS为:

df['signal'].resample('1s').agg(rms)
后者返回:

00:00:00    2.187840e+02
00:00:01    1.979639e+02
00:00:02    1.791252e+02
00:00:03    1.620792e+02
00:00:04    1.466553e+02
信号调节 为了满足您只保留基波(50 Hz)的需要,一个简单的解决方案可以是线性(去除常数和线性趋势),然后是带通滤波器

我们生成具有其他频率和线性趋势的合成信号:

y = np.exp(-0.1*t)*A*(np.sin(2*f*np.pi*t) \
     + 0.2*np.sin(8*f*np.pi*t) + 0.1*np.sin(16*f*np.pi*t)) \
     + A/20*t + A/100
然后我们调节信号:

from scipy import signal
yd = signal.detrend(y, type='linear')
filt = signal.butter(5, [40,60], btype='band', fs=fs, output='sos', analog=False)
yfilt = signal.sosfilt(filt, yd)
从图形上看,它导致:


在RMS计算之前,它将恢复应用信号调节。

欢迎使用,您可以发布一个合成数据集(或生成它的函数)吗以及关于什么是输入和预期输出的详细信息。另外,您是否可以再描述一下您打算执行的操作。使用数学或post参考来确定您的目标的操作定义。干杯,感谢您更新您的帖子。不幸的是,您提供的其他信息没有这么有用。获得输入是一件好事d点,但这是不够的。考虑一下,我们需要重现您的问题,并清楚地了解您的目标。我们缺少的是:如何加载数据,如何将数据提供给函数,最重要的是:预期输出是什么。如果没有这些信息,将很难调查您的问题。P租借考虑阅读,使你的文章符合标准。这样说,你的代码主要依赖于一个带有很多索引和标量运算的for循环。你已经导入了<代码> NoMPy < /Cord>。所以你应该利用矢量化。这将是一个很好的改进起点。nt应用于您的输入和预期输出,我相信我们会找到一种方法来提高性能,以获得更好的响应。我已经给出了我的缩短但有效的代码。对于精确的操作,它应该可以工作。感谢您的更新,我们接近MCVE。我假设一个以50 Hz为中心的带通滤波器就足够了。我喜欢你的建议!我只需要把我的头绕在它周围。使用rfft…我非常喜欢这个主意。再见
00:00:00    2.187840e+02
00:00:01    1.979639e+02
00:00:02    1.791252e+02
00:00:03    1.620792e+02
00:00:04    1.466553e+02
y = np.exp(-0.1*t)*A*(np.sin(2*f*np.pi*t) \
     + 0.2*np.sin(8*f*np.pi*t) + 0.1*np.sin(16*f*np.pi*t)) \
     + A/20*t + A/100
from scipy import signal
yd = signal.detrend(y, type='linear')
filt = signal.butter(5, [40,60], btype='band', fs=fs, output='sos', analog=False)
yfilt = signal.sosfilt(filt, yd)