Source code for mojo.analysis.windowedFFT
"""
windowedFFT - Perform a fast fourier transformation
===================================================
Created on 11.01.2013
author: well_jn
Perform a fast fourier transformation of a real function.
You have the choice of multiple __window functions.
For no windowing use the default values of the constructor.
Choices of __window functions:
HAMMING,
HANNING,
BARTLETT,
BLACKMAN,
FLAT
Example::
from analysis.windowedFFT import WindowedFFT
time = np.arange(0, 1, dt)
myFFT = WindowedFFT(func_timeDomain = np.sin(2 * np.pi * freq * time), d_time = dt, window_type = 'HAMMING', window_size = 50)
freq = myFFT.getFrequencies()
func_freq = myFFT.getSpectrum()
Create a time array and with this a sine function.
Create windowedFFT object with this sine and the choice
for the windowing. You get the frequencies for the positive range of the FFT and
the single single-sided amplitude spectrum of the sine.
requires
--------
numpy
"""
import numpy as np
[docs]class WindowedFFT:
"""
Class to setup a FFT with windowing to get the single-sided amplitude spectrum of a real function
"""
def __init__(self, func_timeDomain, d_time, window_type='FLAT', window_size=0, window_overlap=0):
'''
Constructor of windowedFFTObject object.
'''
self.__func_timeDomain = func_timeDomain
self.__d_time = d_time
self.__window_type = None
self.__window_size = 0
self.__window_overlap = 0
self.__window = None
self.__fft_range = 0
self.__positive_range = 0
self.setWindowType(window_type)
self.setWindowSize(window_size)
self.setWindowOverlap(window_overlap)
def __setupSingleSidedFFT(self):
"""
Check if the necessary information were set by the user and
calculate some additional stuff.
"""
self.__fft_range = self.__window_size // 2 + 1
self.__positive_range = self.__fft_range // 2
def __getWindow(self):
"""
Depending on the windowing string call the numpy function to get
an array with values of the __window.
"""
if self.__window_type == 'HAMMING':
self.__window = np.hamming(self.__window_size)
elif self.__window_type == 'HANNING':
self.__window = np.hanning(self.__window_size)
elif self.__window_type == 'BARTLETT':
self.__window = np.bartlett(self.__window_size)
elif self.__window_type == 'BLACKMAN':
self.__window = np.blackman(self.__window_size)
elif self.__window_type == 'FLAT':
self.__window = np.kaiser(self.__window_size, 0)
else:
raise ValueError("invalid __window type '%s'!" % self.__window_type)
self.__window /= np.sum(self.__window) / self.__window_size
[docs] def setWindowType(self, window_type):
"""
Set which type of windowing you want to use.
Possible choices are:
- HAMMING
- HANNING
- BARTLETT
- BLACKMAN
- FLAT
"""
self.__window_type = window_type.upper()
[docs] def setWindowSize(self, window_size: int):
"""
Set the length of the used window.
"""
self.__window_size = window_size
if self.__window_size > self.__func_timeDomain.size:
raise ValueError('Window size is larger than the length of the data.')
elif self.__window_size < 0:
raise ValueError('Window size must be a positive integer.')
elif self.__window_size == 0:
self.__window_size = self.__func_timeDomain.size
self.__setupSingleSidedFFT()
[docs] def setWindowOverlap(self, window_overlap: int):
"""
Set the overlapping of the window.
"""
if window_overlap < 0:
raise ValueError('Window overlap must be a positive integer.')
elif window_overlap >= self.__window_size:
raise ValueError('Window overlap is larger than the window size.')
self.__window_overlap = window_overlap
[docs] def getSingleSidedFrequencies(self):
"""
Get corresponding frequencies for the resulting spectrum.
"""
freq = np.fft.fftfreq(self.__fft_range, 2 * self.__d_time)
freq = freq[list(range(self.__positive_range))]
return freq
[docs] def getSingleSidedSpectrum(self):
"""
Compute a single-sided amplitude spectrum of a real __func_timeDomain(t) with windowing.
"""
self.__getWindow()
idx = 0
func_freq = np.zeros(self.__fft_range, dtype=complex)
while idx + self.__window_size <= self.__func_timeDomain.size:
func_timeDomain_window = self.__func_timeDomain[idx:idx + self.__window_size]
func_timeDomain_window = self.__window * func_timeDomain_window
func_freq_window = np.fft.rfft(func_timeDomain_window) / self.__window_size
func_freq += func_freq_window
idx += (self.__window_size - self.__window_overlap)
func_freq = 2 * func_freq[list(range(self.__positive_range))]
return func_freq