SciPy的FFT输出令人困惑或可能被误解

huwehgph  于 2022-11-10  发布在  其他
关注(0)|答案(1)|浏览(201)

我正在对一个1D信号应用Scipy软件包中的FFT。这个信号是以512hz的采样率捕获的,这意味着1秒内有512个数据点。我总共有5分钟的数据。
当我使用下面的代码将Scipy中的FFT应用于该信号时,我会将FFT一次应用于整个信号。据我所知,当我以512的采样率对信号应用FFT时,FFT会应用于前512个点,然后是下512个数据点,依此类推,但此处FFT会一次应用于整个信号,这我不理解。

import numpy as np
import pandas as pd
from scipy.stats import zscore
from scipy.fft import fft, fftfreq,rfft, rfftfreq
import matplotlib.pyplot as plt

df =  pd.read_csv("data.csv")
df = df.drop('Unnamed: 0',axis=True)
print(df.head())

# measuring the fft of the signal

def plotFFT(df):#,cleanDF):
    sampleRate = 512 # Hz
    duration = df.shape[0]

    xf = rfftfreq(duration,1/sampleRate)
    yf = rfft(df['value'])

    fig = plt.figure(num='FFT of signal', figsize=(20,10))
    plt.plot(xf,np.real(yf),label='raw')
    plt.legend()
    plt.grid()
    plt.draw()
    plt.waitforbuttonpress(0)
    plt.close(fig)

plotFFT(df)

当我改变路线

yf = rfft(df['value'])

yf = rfft(df['value'],n=sampleRate)

我得到这个错误:

C:\ProgramData\Anaconda3\python.exe C:/Users/BLACK/Desktop/PythonXperiments/FFTScipy/main.py
Traceback (most recent call last):
  File "C:/Users/BLACK/Desktop/PythonXperiments/FFTScipy/main.py", line 29, in <module>
    plotFFT(df)
  File "C:/Users/BLACK/Desktop/PythonXperiments/FFTScipy/main.py", line 21, in plotFFT
    plt.plot(xf, np.real(yf), label='raw')
  File "C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\pyplot.py", line 2840, in plot
    return gca().plot(
  File "C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\axes\_axes.py", line 1743, in plot
    lines = [*self._get_lines(*args, data=data,**kwargs)]
  File "C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 273, in __call__
    yield from self._plot_args(this, kwargs)
  File "C:\ProgramData\Anaconda3\lib\site-packages\matplotlib\axes\_base.py", line 399, in _plot_args
    raise ValueError(f"x and y must have same first dimension, but "
ValueError: x and y must have same first dimension, but have shapes (53378,) and (257,)
zqdjd7g9

zqdjd7g91#

已经一年了,我不知道你是否已经有了解决办法,但我希望我能在这个问题上提供一些线索:
这个程序使用scipy,一个汉宁窗口,并把结果写在一个excel表上,所以我希望这个例子可以帮助人们理解从时间到频率发生了什么。
1.-您需要以admin身份运行此程序2.-Excel文件创建后,将其 checkout ,如果您更改了值,并重新运行程序,您需要关闭Excel文件,或将其另存为另一个文件. 3.-在pyhton 3和windows 10-11中工作


# using openpyxl and scipy... install numpy as well if you don't already have it.

# It's also, VERY, important to run python as administrator (cause openpyxl will write data to your computer, and windows requires python to be running as admin)

# Also, VERY important, close the excel file before attempting to create another one, or save it as something else, other wise you'll get errors

from scipy.fft import rfft
from scipy.signal import hann
import numpy as np
from openpyxl import  load_workbook, Workbook
from openpyxl.styles import Font, Color, colors, PatternFill
from openpyxl.chart import ScatterChart, Reference, Series

sample_rate = 2048                                          # sample rate are values 2^n; 1024, 2048, 4096, etc
N = 2048                                                    # Number of samples taken (multiple of 2.56 - thinking about vibration analysis)
f_max = int(sample_rate/2.56)
lines = N/2.56                                     
wait_time = N/sample_rate                                   # again, in vibration analysis, this is known as the Data Adquisition Time (1s for this example)
jump_c = f_max/lines                                        # This is going to be the delta frequency (maximum frequency divided by samples)

t = np.linspace(0, wait_time, N)
y = (10)*np.sin(2*np.pi*60*t) + (5)*np.sin(2*np.pi*120*t)  # sin function with two components: 60 Hz and 120 Hz you can play with the frequencies as well as amplitudes

win_1 = hann(N)                                             # Hanning window will be used, windows are an entirely different subject, check this out: https://en.wikipedia.org/wiki/Window_function
w_1 = rfft(y*win_1)                                         # this is the real fft of the y function (it will create an array of 2048/2.56) without its negative part
w_1 = np.abs(w_1).astype(int)                               # only caring about the positive values

filename = 'test.xlsx'                                      # this file is going to be over written, you need to run python as admin (if on windows)

wb = Workbook()                                             # Openpyxl config to open and create the first sheet
ws1 = wb.create_sheet('Sheet_A', 0)                         
ws1.title = 'osc to specter'

ws1['A1'].font = Font(bold = True)
ws1.cell(row = 10, column = 1).value = 'time'
ws1.cell(row = 10, column = 2).value = 'original funct'
ws1.cell(row = 10, column = 3).value = 'frec'
ws1.cell(row = 10, column = 4).value = 'frec amplitude'

row_j = 11

for k in range(len(t)):
    ws1.cell(row = row_j, column = 1).value = t[k]*1000     # This to get it on ms
    ws1.cell(row = row_j, column = 2).value = y[k]
    row_j = row_j + 1

chart_1 = ScatterChart()
chart_1.y_axis.title = 'Amplitude'
chart_1.x_axis.title = 'ms'

tvalues = Reference(ws1, min_col = 1, min_row = 11, max_row = row_j)  

yvalues_1 = Reference(ws1, min_col = 2, min_row = 11, max_row = row_j)
series_1 = Series(yvalues_1, tvalues, title = 'Oscillogram')
series_1.graphicalProperties.line.width = 9500
chart_1.x_axis.tickLblPos = 'low'
chart_1.height = 10
chart_1.width = 30
chart_1.x_axis.scaling.max = wait_time*1000                 # Also, to get it on ms
chart_1.x_axis.scaling.min = 0
chart_1.legend = None
chart_1.series.append(series_1)
ws1.add_chart(chart_1, 'F1')

row_i = 11

frec = np.arange(0, f_max, jump_c)

for j in range(len(frec)):

    ws1.cell(row = row_i, column = 3).value = frec[j]
    ws1.cell(row = row_i, column = 4).value = w_1[j]/(len(w_1)/2)     # it needs to be divided, otherwise amplitude is really high

    row_i = row_i + 1

xvalues = Reference(ws1, min_col = 3, min_row = 11, max_row = row_i)

chart_2 = ScatterChart()
chart_2.y_axis.title = 'Amplitude'
chart_2.x_axis.title = 'Hz'

yvalues_2 = Reference(ws1, min_col = 4, min_row = 11, max_row = row_i)
series_2 = Series(yvalues_2, xvalues, title = 'Hanning window')
series_2.graphicalProperties.line.width = 9500 # This is in EMUs, apparently openpyxly transforms this divided by something to obtain pixels; 9500 will give 7.5 px
chart_2.x_axis.tickLblPos = 'low'
chart_2.height = 10
chart_2.width = 30
chart_2.x_axis.scaling.max = f_max
chart_2.x_axis.scaling.min = 0
chart_2.legend = None                        # Otherwise, you could select with legend.position = 'b' (r = right, l = left, t = top, b = bottom, tr = top right. Default is r)
chart_2.series.append(series_2)
ws1.add_chart(chart_2, 'F21')

wb.save(filename)                                                   # Saving 'da' file
print ('saved file')

相关问题