पायथन में तेजी से फूरियर रूपांतरण की साजिश रच रहा है


98

मेरे पास NumPy और SciPy तक पहुंच है और एक डेटा सेट का एक सरल FFT बनाना चाहते हैं। मेरे पास दो सूचियाँ हैं, एक जो yमूल्य है और दूसरी उन yमूल्यों के लिए टाइमस्टैम्प है ।

इन सूचियों को एक SciPy या NumPy विधि में फीड करने और परिणामी FFT को प्लॉट करने का सबसे सरल तरीका क्या है?

मैंने उदाहरणों को देखा है, लेकिन वे सभी कुछ निश्चित डेटा बिंदुओं, और आवृत्ति आदि के साथ नकली डेटा का एक सेट बनाने पर भरोसा करते हैं और वास्तव में यह नहीं दिखाते हैं कि यह डेटा के सेट और संबंधित टाइमस्टैम्प के साथ कैसे किया जाता है। ।

मैंने निम्नलिखित उदाहरण की कोशिश की है:

from scipy.fftpack import fft

# Number of samplepoints
N = 600

# Sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)
import matplotlib.pyplot as plt
plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
plt.grid()
plt.show()

लेकिन जब मैं fftअपने डेटा सेट के तर्क को बदलता हूं और उसे प्लॉट करता हूं, तो मुझे बहुत ही अजीब परिणाम मिलते हैं, और ऐसा प्रतीत होता है कि आवृत्ति के लिए स्केलिंग बंद हो सकती है। मैं अनिश्चित हूं।

यहाँ डेटा का एक पेस्टबिन है जिसे मैं एफएफटी के लिए प्रयास कर रहा हूं

http://pastebin.com/0WhjjMkb http://pastebin.com/ksM4FvZS

जब मैं उपयोग करता हूं fft() पूरी चीज का करता तो बस शून्य पर एक विशाल स्पाइक होता है और कुछ नहीं।

यहाँ मेरा कोड है:

## Perform FFT with SciPy
signalFFT = fft(yInterp)

## Get power spectral density
signalPSD = np.abs(signalFFT) ** 2

## Get frequencies corresponding to signal PSD
fftFreq = fftfreq(len(signalPSD), spacing)

## Get positive half of frequencies
i = fftfreq>0

##
plt.figurefigsize = (8, 4));
plt.plot(fftFreq[i], 10*np.log10(signalPSD[i]));
#plt.xlim(0, 100);
plt.xlabel('Frequency [Hz]');
plt.ylabel('PSD [dB]')

रिक्ति बस के बराबर है xInterp[1]-xInterp[0]


हमें दिखाएं कि आपने क्या प्रयास किया है, यह कैसे विफल हुआ, और जो उदाहरण आप काम कर रहे हैं।
पॉल एच।

मैंने उस उदाहरण को पोस्ट किया जिसकी मैंने कोशिश की थी कि मैं इसके बारे में क्या सोचता हूं, मुझे लगता है कि मैं सिर्फ इस बात पर भ्रमित हूं कि आउटपुट को सही तरीके से कैसे तैयार किया जाए।
user3123955

यह एक महान उदाहरण है, लेकिन वास्तव में समस्या क्या है? वह कोड मेरे लिए बहुत अच्छा काम करता है। क्या प्लॉट बस दिखाई नहीं दे रहा है?
पॉल एच।

अर्थात्, आप किस प्रकार के तर्क का उपयोग कर रहे हैं (हमें आपके कम से कम कुछ डेटा को देखने की आवश्यकता है)
पॉल एच।

मैंने x और y अक्ष के pastebin को जोड़ा है, x डेटा सेकंड में है और y डेटा सिर्फ सेंसर रीडिंग है। जब मैंने डेटा की इन सूचियों को
एफएफटी

जवाबों:


103

इसलिए मैं IPython नोटबुक में आपके कोड का एक कार्यात्मक रूप से समकक्ष रूप से चलाता हूं:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = scipy.fftpack.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)

fig, ax = plt.subplots()
ax.plot(xf, 2.0/N * np.abs(yf[:N//2]))
plt.show()

मुझे वही मिलता है जो मैं मानता हूं कि यह बहुत ही उचित आउटपुट है।

यहां छवि विवरण दर्ज करें

जब से मैं इंजीनियरिंग स्कूल में सिग्नल प्रोसेसिंग के बारे में सोच रहा था, तब से मैं यह मानता हूं कि मैं इसकी देखभाल करता हूं, लेकिन 50 और 80 पर स्पाइक्स ठीक वही हैं जो मैं उम्मीद करूंगा। तो क्या मसला है?

कच्चे डेटा और टिप्पणियों के जवाब में पोस्ट किया जा रहा है

यहाँ समस्या यह है कि आपके पास आवधिक डेटा नहीं है। आपको हमेशा उस डेटा का निरीक्षण करना चाहिए जिसे आप किसी भी एल्गोरिथम में फीड करते हैं ताकि यह सुनिश्चित हो सके कि यह उपयुक्त है।

import pandas
import matplotlib.pyplot as plt
#import seaborn
%matplotlib inline

# the OP's data
x = pandas.read_csv('http://pastebin.com/raw.php?i=ksM4FvZS', skiprows=2, header=None).values
y = pandas.read_csv('http://pastebin.com/raw.php?i=0WhjjMkb', skiprows=2, header=None).values
fig, ax = plt.subplots()
ax.plot(x, y)

यहां छवि विवरण दर्ज करें


1
यह नहीं है कि उदाहरण गलत है, इसका यह है कि मुझे नहीं पता कि इसे कैसे लेना है और इसे अपने डेटा पर लागू करना है।
183 बजे user3123955

1
@ user3123955, सही है। इसलिए हमें आपका डेटा देखने की आवश्यकता है और यदि हम आपकी सहायता करने जा रहे हैं तो यह कैसे विफल होता है।
पॉल एच।

मैंने
पिछलेबिन

2
@ user3123955 तो आप किसी भी FFT एल्गोरिथ्म के बारे में क्या उम्मीद करते हैं? आपको अपना डेटा साफ़ करने की आवश्यकता है।
पॉल एच।

6
@PaulH आवृत्ति पर आयाम नहीं करना चाहिए 50 Hzहो 1और आवृत्ति पर 80 Hzहो 0.5?
फुरकान हाशिम

25

Fft के बारे में महत्वपूर्ण बात यह है कि यह केवल उस डेटा पर लागू किया जा सकता है जिसमें टाइमस्टैम्प एक समान है ( अर्थात समय में एक समान नमूना, जैसा आपने ऊपर दिखाया है)।

गैर-समान नमूनाकरण के मामले में, कृपया डेटा फिटिंग के लिए एक फ़ंक्शन का उपयोग करें। चुनने के लिए कई ट्यूटोरियल और फ़ंक्शन हैं:

https://github.com/tiagopereira/python_tips/wiki/Scipy%3A-curve-fitting http://docs.scipy.org/doc/numpy/reference/generated-numpy.polyfit.html

यदि फिटिंग एक विकल्प नहीं है, तो आप डेटा को एक समान नमूने के लिए प्रक्षेपित करने के लिए सीधे प्रक्षेप के कुछ रूप का उपयोग कर सकते हैं:

https://docs.scipy.org/doc/scipy-0.14.0/reference/tutorial/interpolate.html

जब आपके पास एक समान नमूने होंगे, तो आपको t[1] - t[0]अपने नमूनों के समय डेल्टा ( ) के बारे में चिंतित होना पड़ेगा । इस मामले में, आप सीधे fft फ़ंक्शन का उपयोग कर सकते हैं

Y    = numpy.fft.fft(y)
freq = numpy.fft.fftfreq(len(y), t[1] - t[0])

pylab.figure()
pylab.plot( freq, numpy.abs(Y) )
pylab.figure()
pylab.plot(freq, numpy.angle(Y) )
pylab.show()

इससे आपकी समस्या का समाधान हो जाना चाहिए।


3
मैंने अपने डेटा को स्पेसिंग के लिए भी इंटरपोल किया है, क्या आप मुझे बता सकते हैं कि fftfreq क्या करता है? इसे मेरे एक्स अक्ष की आवश्यकता क्यों है? आप वाई और कोण के एब्स की साजिश क्यों करते हैं? चरण कोण है? किस चरण के सापेक्ष है? जब मैं अपने डेटा के साथ ऐसा करता हूं तो बस 0Hz पर एक विशाल शिखर होता है और बहुत जल्दी से बंद हो जाता है, लेकिन मैं इसे डेटा खिला रहा हूं जिसमें निरंतर ऑफसेट नहीं है (मैं किनारों पर डेटा का एक बड़ा बैंडपास करता हूं। 0.15 Gz से 12Hz निरंतर ऑफसेट से छुटकारा पाने के लिए, मेरा डेटा वैसे भी 4 हर्ट्ज से बड़ा नहीं होना चाहिए ताकि बैंड मुझे जानकारी खो दे)।
user3123955

3
1. fftfreqआप अपने डेटा के अनुरूप आवृत्ति घटक देता है। यदि आप प्लॉट freqकरते हैं तो आप देखेंगे कि एक्स-एक्सिस एक ऐसा फंक्शन नहीं है जो बढ़ता रहता है। आपको यह सुनिश्चित करना होगा कि आपके पास x- अक्ष में सही आवृत्ति घटक हैं। आप मैनुअल को देख सकते हैं: docs.scipy.org/doc/numpy/reference/generated/…
ssm

3
2. ज्यादातर लोग एफटी के परिमाण और चरण को देखना पसंद करेंगे। एक वाक्य में इसकी व्याख्या करना मुश्किल है कि चरण की जानकारी आपको क्या बताने जा रही है, लेकिन मैं केवल इतना कह सकता हूं कि जब आप संकेतों को जोड़ते हैं तो यह सार्थक होता है। जब आप एक ही आवृत्ति के संकेतों को जोड़ते हैं जो चरण में होते हैं तो वे बढ़ जाते हैं, जबकि जब वे 180 डिग्री से चरण से बाहर हो जाते हैं, तो वे भाग लेंगे। यह महत्वपूर्ण हो जाता है जब आप एम्पलीफायरों को डिज़ाइन करते हैं या किसी भी तरह का फीडबैक देते हैं।
ssm

3
3. आम तौर पर, आपकी सबसे कम आवृत्ति में व्यावहारिक रूप से शून्य चरण होगा, और यह इसके संदर्भ में है। जब सिग्नल आपके सिस्टम से गुजरते हैं, तो हर आवृत्ति एक अलग वेग के साथ चलती है। यह चरण वेग है। चरण प्लॉट आपको इसकी जानकारी देता है। मैं नहीं जानता कि आप किसके साथ काम कर रहे हैं, इसलिए खिचड़ी भाषा आपको निश्चित जवाब देती है। इस तरह के सवालों के लिए, फीडबैक कंट्रोल, एनालॉग एलेक्रॉनिक्स, डिजिटल सिग्नल प्रोसेसिंग, इलेक्ट्रोमैगनेटिक फील्ड थ्योरी आदि पर पढ़ना बेहतर है, या ऐसा कुछ जो आपके सिस्टम के लिए अधिक विशिष्ट हो।
ssm

4
4. अपने डेटा का उपयोग करने के बजाय , क्यों न आप अपने स्वयं के सिग्नल उत्पन्न करके शुरू करें t = linspace(0, 10, 1000); ys = [ (1.0/i)*sin(i*t) for i in arange(10)]; y = reduce(lambda m, n: m+n, ys):। फिर प्रत्येक ysऔर कुल का प्लॉट करें और yप्रत्येक कंपोनेंट का फफ्ट प्राप्त करें। आप अपनी प्रोग्रामिंग के साथ आत्मविश्वास हासिल करेंगे। फिर आप अपने परिणाम की प्रामाणिकता का न्याय कर सकते हैं। यदि आप जिस सिग्नल का विश्लेषण करने का प्रयास कर रहे हैं, वह पहला ऐसा है जिसे आपने कभी लिया है तो आप हमेशा महसूस करेंगे कि आप कुछ गलत कर रहे हैं ...
ssm

12

आपके पास जो उच्च स्पाइक है वह आपके सिग्नल के डीसी (गैर-भिन्न, यानी फ्रीक = 0) हिस्से के कारण है। यह स्केल का मुद्दा है। यदि आप गैर-डीसी आवृत्ति सामग्री देखना चाहते हैं, तो विज़ुअलाइज़ेशन के लिए, आपको सिग्नल के एफएफटी के ऑफसेट 0 से ऑफसेट 1 से प्लॉट करने की आवश्यकता हो सकती है।

@PaulH द्वारा ऊपर दिए गए उदाहरण को संशोधित करना

import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

# Number of samplepoints
N = 600
# sample spacing
T = 1.0 / 800.0
x = np.linspace(0.0, N*T, N)
y = 10 + np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = scipy.fftpack.fft(y)
xf = np.linspace(0.0, 1.0/(2.0*T), N/2)

plt.subplot(2, 1, 1)
plt.plot(xf, 2.0/N * np.abs(yf[0:N/2]))
plt.subplot(2, 1, 2)
plt.plot(xf[1:], 2.0/N * np.abs(yf[0:N/2])[1:])

आउटपुट प्लॉट: डीसी के साथ FFT सिग्नल प्लॉट करना और फिर इसे हटाते समय (freq = 0 को छोड़ना)

दूसरा तरीका, लॉग स्केल में डेटा की कल्पना करना है:

का उपयोग करते हुए:

plt.semilogy(xf, 2.0/N * np.abs(yf[0:N/2]))

दिखाएंगे: यहां छवि विवरण दर्ज करें


हाँ, यह हर्ट्ज में है। कोड में, xfनक्शों की परिभाषा fft के आवृत्तियों को काटती है।
hesham_EE

1
अच्छा! और कैसे y अक्ष के बारे में? आयाम? आपका बहुत बहुत धन्यवाद_ईएम
विक्टर अगुइर

हाँ, y- अक्ष जटिल fft का पूर्ण मूल्य है। नोटिस का उपयोग करेंnp.abs()
hesham_EE

8

बस पहले से दिए गए उत्तरों के पूरक के रूप में, मैं यह बताना चाहता हूं कि अक्सर एफएफटी के लिए डिब्बे के आकार के साथ खेलना महत्वपूर्ण होता है। यह मूल्यों के एक समूह का परीक्षण करने और आपके आवेदन के लिए अधिक समझ बनाने वाले को चुनने के लिए समझ में आएगा। अक्सर, यह नमूनों की संख्या के समान परिमाण में होता है। यह दिए गए अधिकांश उत्तरों के अनुसार था, और महान और उचित परिणाम देता है। यदि कोई ऐसा पता लगाना चाहता है, तो यहां मेरा कोड संस्करण है:

%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

fig = plt.figure(figsize=[14,4])
N = 600           # Number of samplepoints
Fs = 800.0
T = 1.0 / Fs      # N_samps*T (#samples x sample period) is the sample spacing.
N_fft = 80        # Number of bins (chooses granularity)
x = np.linspace(0, N*T, N)     # the interval
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)   # the signal

# removing the mean of the signal
mean_removed = np.ones_like(y)*np.mean(y)
y = y - mean_removed

# Compute the fft.
yf = scipy.fftpack.fft(y,n=N_fft)
xf = np.arange(0,Fs,Fs/N_fft)

##### Plot the fft #####
ax = plt.subplot(121)
pt, = ax.plot(xf,np.abs(yf), lw=2.0, c='b')
p = plt.Rectangle((Fs/2, 0), Fs/2, ax.get_ylim()[1], facecolor="grey", fill=True, alpha=0.75, hatch="/", zorder=3)
ax.add_patch(p)
ax.set_xlim((ax.get_xlim()[0],Fs))
ax.set_title('FFT', fontsize= 16, fontweight="bold")
ax.set_ylabel('FFT magnitude (power)')
ax.set_xlabel('Frequency (Hz)')
plt.legend((p,), ('mirrowed',))
ax.grid()

##### Close up on the graph of fft#######
# This is the same histogram above, but truncated at the max frequence + an offset. 
offset = 1    # just to help the visualization. Nothing important.
ax2 = fig.add_subplot(122)
ax2.plot(xf,np.abs(yf), lw=2.0, c='b')
ax2.set_xticks(xf)
ax2.set_xlim(-1,int(Fs/6)+offset)
ax2.set_title('FFT close-up', fontsize= 16, fontweight="bold")
ax2.set_ylabel('FFT magnitude (power) - log')
ax2.set_xlabel('Frequency (Hz)')
ax2.hold(True)
ax2.grid()

plt.yscale('log')

उत्पादन भूखंड: यहां छवि विवरण दर्ज करें


6

मैंने एक फ़ंक्शन बनाया है जो वास्तविक संकेतों के FFT की साजिश रचने से संबंधित है। पिछले उत्तरों के सापेक्ष मेरे कार्य में अतिरिक्त बोनस यह है कि आपको सिग्नल के वास्तविक आयाम मिलते हैं ।

इसके अलावा, एक वास्तविक संकेत की धारणा के कारण, एफएफटी सममित है, इसलिए हम केवल एक्स-अक्ष के सकारात्मक पक्ष की साजिश कर सकते हैं:

import matplotlib.pyplot as plt
import numpy as np
import warnings


def fftPlot(sig, dt=None, plot=True):
    # Here it's assumes analytic signal (real signal...) - so only half of the axis is required

    if dt is None:
        dt = 1
        t = np.arange(0, sig.shape[-1])
        xLabel = 'samples'
    else:
        t = np.arange(0, sig.shape[-1]) * dt
        xLabel = 'freq [Hz]'

    if sig.shape[0] % 2 != 0:
        warnings.warn("signal preferred to be even in size, autoFixing it...")
        t = t[0:-1]
        sig = sig[0:-1]

    sigFFT = np.fft.fft(sig) / t.shape[0]  # Divided by size t for coherent magnitude

    freq = np.fft.fftfreq(t.shape[0], d=dt)

    # Plot analytic signal - right half of frequence axis needed only...
    firstNegInd = np.argmax(freq < 0)
    freqAxisPos = freq[0:firstNegInd]
    sigFFTPos = 2 * sigFFT[0:firstNegInd]  # *2 because of magnitude of analytic signal

    if plot:
        plt.figure()
        plt.plot(freqAxisPos, np.abs(sigFFTPos))
        plt.xlabel(xLabel)
        plt.ylabel('mag')
        plt.title('Analytic FFT plot')
        plt.show()

    return sigFFTPos, freqAxisPos


if __name__ == "__main__":
    dt = 1 / 1000

    # Build a signal within Nyquist - the result will be the positive FFT with actual magnitude
    f0 = 200  # [Hz]
    t = np.arange(0, 1 + dt, dt)
    sig = 1 * np.sin(2 * np.pi * f0 * t) + \
        10 * np.sin(2 * np.pi * f0 / 2 * t) + \
        3 * np.sin(2 * np.pi * f0 / 4 * t) +\
        7.5 * np.sin(2 * np.pi * f0 / 5 * t)

    # Result in frequencies
    fftPlot(sig, dt=dt)
    # Result in samples (if the frequencies axis is unknown)
    fftPlot(sig)

विश्लेषणात्मक एफएफटी प्लॉट परिणाम


5

इस पृष्ठ पर पहले से ही महान समाधान हैं, लेकिन सभी ने मान लिया है कि डेटासेट समान / समान रूप से नमूना / वितरित किया गया है। मैं बेतरतीब ढंग से नमूना डेटा का एक और सामान्य उदाहरण प्रदान करने का प्रयास करूंगा। मैं इस MATLAB ट्यूटोरियल का भी उपयोग करूंगा एक उदाहरण के रूप में :

आवश्यक मॉड्यूल जोड़ना:

import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack
import scipy.signal

नमूना डेटा उत्पन्न करना:

N = 600 # Number of samples
t = np.random.uniform(0.0, 1.0, N) # Assuming the time start is 0.0 and time end is 1.0
S = 1.0 * np.sin(50.0 * 2 * np.pi * t) + 0.5 * np.sin(80.0 * 2 * np.pi * t)
X = S + 0.01 * np.random.randn(N) # Adding noise

डेटा सेट को क्रमबद्ध करना:

order = np.argsort(t)
ts = np.array(t)[order]
Xs = np.array(X)[order]

रीसेंपलिंग:

T = (t.max() - t.min()) / N # Average period
Fs = 1 / T # Average sample rate frequency
f = Fs * np.arange(0, N // 2 + 1) / N; # Resampled frequency vector
X_new, t_new = scipy.signal.resample(Xs, N, ts)

डेटा और resampled डेटा प्लॉटिंग:

plt.xlim(0, 0.1)
plt.plot(t_new, X_new, label="resampled")
plt.plot(ts, Xs, label="org")
plt.legend()
plt.ylabel("X")
plt.xlabel("t")

यहां छवि विवरण दर्ज करें

अब एफएफटी की गणना:

Y = scipy.fftpack.fft(X_new)
P2 = np.abs(Y / N)
P1 = P2[0 : N // 2 + 1]
P1[1 : -2] = 2 * P1[1 : -2]

plt.ylabel("Y")
plt.xlabel("f")
plt.plot(f, P1)

यहां छवि विवरण दर्ज करें

पी एस मैं अंत में असमान रूप से वितरित डेटा के फूरियर रूपांतरण प्राप्त करने के लिए एक अधिक विहित एल्गोरिथ्म को लागू करने का समय मिला। आप यहां ज्यूप्टर नोटबुक का कोड, विवरण और उदाहरण देख सकते हैं ।


मैं डॉक्स में कुछ भी नहीं देख रहा हूं जो सुझाव देता resampleहै कि गैर-वर्दी नमूना समय संभालता है। यह एक समय पैरामीटर (जो उदाहरण में उपयोग नहीं किया गया है) को स्वीकार करता है, लेकिन ऐसा लगता है कि समान नमूना समय भी।
user2699

@ user2699 इस उदाहरण की मदद कर सकता है
Foad

2
'scipy.signal.resample` डेटा को फिर से भरने के लिए FFT विधि का उपयोग करता है। यह एक समान FFT पाने के लिए गैर-वर्दी डेटा को फिर से शुरू करने के लिए इसका उपयोग करने का कोई मतलब नहीं है।
user2699

1
@ user2699 ऐसा लगता है कि मैं यहाँ बहुत भोली थी। पहले से ही कुछ पुस्तकालय उपलब्ध हैं: 1. एनएफटी लाइब्रेरी जो एनएफएफटी के आसपास एक आवरण लगती हैpyNFFT और 3. PyNUFFT
Foad

2
आपके द्वारा दिए गए सभी तरीकों के फायदे और नुकसान हैं (हालांकि ध्यान दें कि sklearn.utils.resampleप्रक्षेप नहीं करता है)। यदि आप अनियमित रूप से सैंपल सिग्नल, या विभिन्न प्रकार के प्रक्षेप के गुणों को खोजने के लिए उपलब्ध विकल्पों पर चर्चा करना चाहते हैं, तो कृपया एक और प्रश्न शुरू करें। दोनों दिलचस्प विषय हैं, लेकिन एफएफटी को कैसे प्लॉट किया जाए, इस पर उत्तरों के दायरे से परे।
14:26 पर user2699

4

मैं FFT का उपयोग करते समय स्पाइक्स के प्रसार की उत्पत्ति की व्याख्या करने के लिए यह अतिरिक्त उत्तर लिखता हूं और विशेष रूप से scipy.fftpack ट्यूटोरियल पर चर्चा करता हूं जिसके साथ मैं कुछ बिंदु पर असहमत हूं।

इस उदाहरण में, रिकॉर्डिंग समय tmax=N*T=0.75। संकेत है sin(50*2*pi*x) + 0.5*sin(80*2*pi*x)। आवृत्ति संकेत में आवृत्तियों पर 50और 80एम्पलीट्यूड के साथ दो स्पाइक्स होने चाहिए 1और 0.5। हालाँकि, यदि विश्लेषण किए गए सिग्नल में पूर्णांक संख्या नहीं है, तो संकेत की छंटनी के कारण प्रसार की अवधि दिखाई दे सकती है:

  • पाईक 1: 50*tmax=37.5=> आवृत्ति इस आवृत्ति पर संकेत छंटनी के कारण प्रसार50 का एक 1/tmax= = प्रसार की उपस्थिति नहीं है ।
  • पाईक 2: 80*tmax=60=> आवृत्ति इस आवृत्ति पर सिग्नल ट्रंकेशन के कारण 80बहुविध 1/tmax=> कोई प्रसार नहीं है

यहां एक कोड है जो ट्यूटोरियल में उसी सिग्नल का विश्लेषण करता है ( sin(50*2*pi*x) + 0.5*sin(80*2*pi*x)), लेकिन थोड़े अंतर के साथ:

  1. मूल scipy.fftpack उदाहरण।
  2. सिग्नल अवधि की पूर्णांक संख्या ( tmax=1.0इसके बजाय) के साथ मूल scipy.fftpack उदाहरण0.75 प्रसार से बचने लिए) के ।
  3. मूल scipy.fftpack उदाहरण काल ​​की पूर्णांक संख्या के साथ उदाहरण और जहां दिनांक और आवृत्तियों को एफएफटी सिद्धांत से लिया जाता है।

कोड:

import numpy as np
import matplotlib.pyplot as plt
import scipy.fftpack

# 1. Linspace
N = 600
# Sample spacing
tmax = 3/4
T = tmax / N # =1.0 / 800.0
x1 = np.linspace(0.0, N*T, N)
y1 = np.sin(50.0 * 2.0*np.pi*x1) + 0.5*np.sin(80.0 * 2.0*np.pi*x1)
yf1 = scipy.fftpack.fft(y1)
xf1 = np.linspace(0.0, 1.0/(2.0*T), N//2)

# 2. Integer number of periods
tmax = 1
T = tmax / N # Sample spacing
x2 = np.linspace(0.0, N*T, N)
y2 = np.sin(50.0 * 2.0*np.pi*x2) + 0.5*np.sin(80.0 * 2.0*np.pi*x2)
yf2 = scipy.fftpack.fft(y2)
xf2 = np.linspace(0.0, 1.0/(2.0*T), N//2)

# 3. Correct positioning of dates relatively to FFT theory ('arange' instead of 'linspace')
tmax = 1
T = tmax / N # Sample spacing
x3 = T * np.arange(N)
y3 = np.sin(50.0 * 2.0*np.pi*x3) + 0.5*np.sin(80.0 * 2.0*np.pi*x3)
yf3 = scipy.fftpack.fft(y3)
xf3 = 1/(N*T) * np.arange(N)[:N//2]

fig, ax = plt.subplots()
# Plotting only the left part of the spectrum to not show aliasing
ax.plot(xf1, 2.0/N * np.abs(yf1[:N//2]), label='fftpack tutorial')
ax.plot(xf2, 2.0/N * np.abs(yf2[:N//2]), label='Integer number of periods')
ax.plot(xf3, 2.0/N * np.abs(yf3[:N//2]), label='Correct positioning of dates')
plt.legend()
plt.grid()
plt.show()

आउटपुट:

जैसा कि यह यहां हो सकता है, यहां तक ​​कि पूर्णांक संख्याओं का उपयोग करके कुछ प्रसार अभी भी बना हुआ है। यह व्यवहार scipy.fftpack ट्यूटोरियल में दिनांक और आवृत्तियों की खराब स्थिति के कारण है। इसलिए, असतत फूरियर रूपांतरण के सिद्धांत में:

  • सिग्नल का मूल्यांकन उन तिथियों पर किया जाना चाहिए t=0,T,...,(N-1)*Tजहां T नमूना अवधि है और संकेत की कुल अवधि है tmax=N*T। ध्यान दें कि हम पर रोक tmax-T
  • संबंधित आवृत्तियाँ नमूने की आवृत्ति f=0,df,...,(N-1)*dfकहाँ df=1/tmax=1/(N*T)है। संकेत के सभी हार्मोनिक्स विसरण से बचने के लिए नमूना आवृत्ति के कई होने चाहिए।

ऊपर दिए गए उदाहरण में, आप देख सकते हैं कि आवृत्ति स्पेक्ट्रम में अतिरिक्त प्रसार से बचने के लिए सक्षम के arangeबजाय का उपयोग linspace। इसके अलावा, का उपयोग करlinspace संस्करण भी स्पाइक्स की भरपाई होती है, जो कि जितनी होनी चाहिए, उससे थोड़ी अधिक आवृत्तियों पर स्थित होती हैं, यह पहली तस्वीर में देखा जा सकता है, जहां स्पाइक्स आवृत्तियों के दाईं ओर थोड़ा सा होते हैं 50और80

मैं केवल यह निष्कर्ष निकालता हूं कि उपयोग का उदाहरण निम्नलिखित कोड द्वारा प्रतिस्थापित किया जाना चाहिए (जो मेरी राय में कम भ्रामक है):

import numpy as np
from scipy.fftpack import fft

# Number of sample points
N = 600
T = 1.0 / 800.0
x = T*np.arange(N)
y = np.sin(50.0 * 2.0*np.pi*x) + 0.5*np.sin(80.0 * 2.0*np.pi*x)
yf = fft(y)
xf = 1/(N*T)*np.arange(N//2)
import matplotlib.pyplot as plt
plt.plot(xf, 2.0/N * np.abs(yf[0:N//2]))
plt.grid()
plt.show()

आउटपुट (दूसरा स्पाइक अब विसरित नहीं है):

मुझे लगता है कि यह उत्तर अभी भी सही ढंग से असतत फूरियर रूपांतरण को लागू करने के बारे में कुछ अतिरिक्त स्पष्टीकरण लाता है। जाहिर है, मेरा जवाब बहुत लंबा है और कहने के लिए हमेशा अतिरिक्त चीजें होती हैं ( उदाहरण के लिए एलियासिंग के बारे में संक्षेप में बात की गई है और बहुत कुछ कहा जा सकता है विंडोइंग ), इसलिए मैं रुक ।

मुझे लगता है कि इसे लागू करते समय असतत फूरियर रूपांतरण के सिद्धांतों को गहराई से समझना बहुत महत्वपूर्ण है क्योंकि हम सभी जानते हैं कि यहां बहुत सारे लोग कारकों को जोड़ रहे हैं और इसे लागू करने के लिए कि वे क्या चाहते हैं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.