FFT/Fourier Transforms in IronPython QuickStart Sample

Illustrates how to compute the forward and inverse Fourier transform of a real or complex signal using classes in the Extreme.Mathematics.SignalProcessing namespace in IronPython.

View this sample in: C# Visual Basic F#

import numerics

from math import *

from Extreme.Mathematics import *
# We'll need real vectors...
from Extreme.Mathematics.LinearAlgebra import *
# and complex vectors...
from Extreme.Mathematics.LinearAlgebra.Complex import *
# The FFT classes reside in the Extreme.Mathematics.SignalProcessing
# namespace.
from Extreme.Mathematics.SignalProcessing import *

# Illustrates the use of the FftProvider and Fft classes for computing 
# the Fourier transform of real and complex signals.

# This QuickStart sample shows how to compute the Fouier
# transform of real and complex signals.

# Some vectors to play with:
r1 = Vector([ 1.0 / (1 + i) for i in xrange(1000)])
c1 = ComplexVector.Create(1000, lambda i: DoubleComplex(sin(0.03 * i), cos(0.07 * i)))

r2 = Vector([ 1.0, 2.0, 3.0, 4.0 ])
c2 = ComplexVector([ 1+2j, 3+4j, 5+6j, 7+8j ])

# One-time FFT's

# The Vector and ComplexVector classes have static methods to compute FFT's:
c3 = Vector.FourierTransform(r2)
r3 = Vector.InverseFourierTransform(c3)
print "fft(r2) = {0:.3f}".format(c3)
print "ifft(fft(r2)) = {0:.3f}".format(r3)
# The ComplexConjugateSignalVector type represents a complex vector
# that is the Fourier transform of a real signal. 
# It enforces certain symmetry properties:
print "c3[i] == conj(c3[N-i]): {0} == conj({1})".format(c3[1], c3[3])

# FFT Providers

# FFT's require a fair bit of pre-computation. Using the FftProvider class, # you can get an Fft object that caches these computations.

# Here, we create an FFT implementation for a real signal:
realFft = FftProvider.ManagedProvider.Create1DRealFft(r1.Length)
# For a complex to complex transform:
complexFft = FftProvider.ManagedProvider.Create1DComplexFft(c1.Length)

# You can set the scale factor for the forward transform.
# The default is 1/N.
realFft.ForwardScaleFactor = 1.0 / sqrt(c1.Length)
# and the backward transform, with default 1:
realFft.BackwardScaleFactor = realFft.ForwardScaleFactor

# The ForwardTransform method performs a forward transform:
c4 = realFft.ForwardTransform(r1)
print "First 5 terms of fft(r1):"
for i in range(0,5):
    print "   {0}: {1}".format(i, c4[i])
c4 = complexFft.ForwardTransform(c1)
print "First 5 terms of fft(c1):"
for i in range(0,5):
    print "   {0}: {1}".format(i, c4[i])

# ForwardTransform has many overloads for real to complex and
# complex to complex transforms.

# A one-sided transform returns only the first half of the FFT of
# a real signal. The rest can be deduced from the symmetry properties.
# Here's how to compute a one-sided FFT:
c5 = ComplexVector.Create(r1.Length / 2 + 1)
realFft.ForwardTransform(r1, c5, RealFftFormat.OneSided)

# The BackwardTransform method has a similar set of overloads:
r4 = Vector.Create(r1.Length)
realFft.BackwardTransform(c5, r4, RealFftFormat.OneSided)

# As the last step, we need to dispose the two FFT implementations.

# 2D transforms

# 2D transforms are handled in a completely analogous way.
m = Matrix.Create(36, 56, lambda i,j: exp(-0.1 * i) * sin(0.01 * (i * i + j * j - i * j)))
mFft = ComplexMatrix.Create(m.RowCount, m.ColumnCount)

with FftProvider.CurrentProvider.Create2DRealFft(m.RowCount, m.ColumnCount) as fft2:
    fft2.ForwardTransform(m, mFft)

    print "First few terms of fft(m):"
    print format(mFft[0:5,0:5], ".3f")

    # and the backward transform:
    fft2.BackwardTransform(mFft, m)

    # Dispose is called automatically.