Initial
This commit is contained in:
58
fft.py
Normal file
58
fft.py
Normal file
@@ -0,0 +1,58 @@
|
||||
import numpy as np
|
||||
|
||||
|
||||
def fft(x, fs, X_nom=None, epsilon=None):
|
||||
|
||||
# Implementation from IEC 61000-4-7:2002/AMD1:2008
|
||||
|
||||
|
||||
# Data length
|
||||
N = len(x)
|
||||
# Number of positive-frequency bins
|
||||
K = int(np.floor(N/2))
|
||||
# Frequency axis (0 .. fs/2)
|
||||
#freq = np.linspace(start=0, stop=fs/2, num=K+1, endpoint=True)
|
||||
freq = np.arange(K + 1) * fs / N
|
||||
|
||||
# allocate
|
||||
a = np.zeros(K + 1)
|
||||
b = np.zeros(K + 1)
|
||||
c = np.zeros(K + 1)
|
||||
Y_C = np.zeros(K + 1)
|
||||
phi = np.zeros(K + 1)
|
||||
|
||||
n = np.arange(N)
|
||||
|
||||
# DC
|
||||
c[0] = np.mean(x) # c0 per IEC
|
||||
a[0] = 2 * c[0] # not really used; just for completeness
|
||||
b[0] = 0.0
|
||||
|
||||
# k = 1..K
|
||||
for k in range(1, K+1):
|
||||
angle = 2 * np.pi * k * n / N
|
||||
a[k] = (2/N) * np.sum(x * np.cos(angle))
|
||||
b[k] = (2/N) * np.sum(x * np.sin(angle))
|
||||
|
||||
# Nyquist (if N even): do NOT apply the 2/N doubling
|
||||
if (N % 2 == 0) and (k == K):
|
||||
a[k] *= 0.5
|
||||
b[k] *= 0.5
|
||||
c[k] = np.sqrt(a[k]*a[k] + b[k]*b[k])
|
||||
|
||||
# RMS value calculated in Eq.2.
|
||||
Y_C[k] = c[k] / np.sqrt(2)
|
||||
|
||||
|
||||
# Phase: apply dead-band if provided, else always compute
|
||||
if (X_nom is not None) and (epsilon is not None):
|
||||
if (np.abs(a[k]) <= epsilon * X_nom) and (np.abs(b[k]) <= epsilon * X_nom):
|
||||
phi[k] = 0.0
|
||||
continue
|
||||
|
||||
# IEC quadrant handling (equivalent to the piecewise definition)
|
||||
phi[k] = np.arctan2(a[k], b[k])
|
||||
|
||||
|
||||
|
||||
return freq, a, b, c, Y_C, phi
|
||||
Reference in New Issue
Block a user