Discrete Fourier Transform

#dft #fft #fourier

Testing the code for the DFT algorithm written in julia

In dft1, I naively translate the C algorithm into julia without take advantage of julia's complex values

The length in dft1 is twice the length that it should be becuase the complex values are being stored as indata[n] is real and indata[n+1] is imaginary, where \(n = 0,2,4,...\)

I implemented my algrorithm as dft2 which was optimized to use the complex values of julia ( also because this made it easier to implement ). I used linspace function to generate a 1000 points of the Sine function and ran it through the algorithm. dft2 generated questionable out put. Comparing this to Jim's version I implemented in julia, dft3, it is clear the outout of my dft2 is not correct. I'll need to go through it again and look at what I did wrong. It may be an error in translating it from C to julia but it could also be an error in my math.

#discretefourier #dft1 #Oct23_13
In [1]:
function dft1(indata, outdata)
    sumreal = sumimag = 0
    N = length(indata)/2.0
    for i in [0:N-1]
        for k in [0:N-1]
                        sumreal += indata[2*k] * cos(2 * pi * k * i / N) + indata[2*k+1] * sin(2 * pi * k * i / N)
                        sumimag += -indata[2*k] * sin(2 * pi * k * i / N) + indata[2*k+1] * cos(2 * pi * k * i / N)
        end
        
        outdata[2*i]   = sumreal
        outdata[2*i+1] = sumimag 
    end
end
    
Out[1]:
dft1 (generic function with 1 method)
#dft2 #fourier
In [16]:
function dft2(indata)
    sumreal = sumimag = 0
    N = length(indata)
    outdata = Array(Complex, N)
    for i in [1:N]
        for k in [1:N]
                        sumreal += real(indata[k]) * cos(2 * pi * k * i / N) + imag(indata[k]) * sin(2 * pi * k * i / N)
                        sumimag += -real(indata[k]) * sin(2 * pi * k * i / N) + imag(indata[k]) * cos(2 * pi * k * i / N)
        end
        
        outdata[i] = complex(sumreal,sumimag) 
    end
    
    return outdata
end
Out[16]:
dft2 (generic function with 2 methods)
In [18]:
Z = dft2(Y)
Out[18]:
1000-element Array{Complex{T<:Real},1}:
         -1.57001-499.747im
         -1.56581-499.079im
         -1.56227-498.703im
         -1.55892-498.436im
         -1.55564-498.228im
         -1.55241-498.056im
          -1.54919-497.91im
           -1.546-497.783im
         -1.54282-497.671im
          -1.53964-497.57im
         -1.53647-497.478im
          -1.5333-497.394im
         -1.53014-497.316im
                          ⋮
           1.53964-497.57im
          1.54282-497.671im
            1.546-497.783im
           1.54919-497.91im
          1.55241-498.056im
          1.55564-498.228im
          1.55892-498.436im
          1.56227-498.703im
          1.56581-499.079im
          1.57001-499.747im
 -1.09504e-10+2.92101e-12im
 -1.09462e-10-3.53962e-11im
#dft3
In [26]:
function dft3(indata)
    N = length(indata)
    omega = exp( -1im * 2pi / N)
    outdata = Array(Complex, N)
    for i in [1:N]
        for k in [1:N]
            outdata[i] = indata[i] * omega^(i*k)
        end
    end
    
    return outdata
end
Out[26]:
dft3 (generic function with 1 method)
In [27]:
B = dft3(Y)
Out[27]:
1000-element Array{Complex{T<:Real},1}:
                  0.0+0.0im
   0.00628943-5.58614e-18im
            0.0125786+0.0im
    0.0188673-3.35151e-17im
    0.0251552+1.56396e-16im
            0.0314422+0.0im
    0.0377279-3.35091e-16im
    0.0440121-1.56362e-16im
    0.0502946+3.23862e-16im
     0.056575+7.03482e-16im
    0.0628533-6.69899e-16im
             0.069129+0.0im
    0.0754021+2.00911e-16im
                          ⋮
    -0.069129-1.79592e-14im
   -0.0628533-1.45145e-14im
    -0.056575-1.62052e-14im
   -0.0502946+1.07209e-14im
   -0.0440121+7.01676e-15im
   -0.0377279+7.97517e-15im
   -0.0314422+6.80005e-15im
   -0.0251552+4.91532e-15im
   -0.0188673+2.40471e-15im
   -0.0125786+1.69815e-15im
  -0.00628943+8.77024e-16im
 -2.44929e-16-2.69751e-29im

On Plotting

In [29]:
using PyPlot
plot(real(B),imag(B))
title("Test plot of Sine")
xlabel("Frequency")
Out[29]:
PyObject <matplotlib.text.Text object at 0x111ee1410>
Warning: Possible conflict in library symbol dtrtri_
Warning: Possible conflict in library symbol dgetri_
Warning: Possible conflict in library symbol dgetrf_

Well, that didn't work :

In [32]:
plot([1:1000]/1000.0,real(B))
title("Test plot of Sine in Frequency domain 2")
xlabel("Frequency")
Out[32]:
PyObject <matplotlib.text.Text object at 0x112db4f90>

wait, what? Now, I'm kinda confused. Why did I just get the sin wave back? I thought there would be a spike at one frequency...

In [31]:
plot([1:1000]/1000.0,imag(B))
title("Test plot of Sine in frequency domain 3")
xlabel("Frequency")
Out[31]:
PyObject <matplotlib.text.Text object at 0x112d8b550>

Okay, so the imaginary plot did not reval anything. It looks like garbage due to arithmetic artifacts. In the Test plot of Sine in frequency domain 2 I think what its telling me is that the sine wave is being approximated by a series of different sine waves which happend to have thier frequencies defined by a sine function. Unless, I did something wrong and that is total bullshit.

Scratchwork

#scratch #scratchwork #ineedsleep
In [19]:
Z
Out[19]:
1000-element Array{Complex{T<:Real},1}:
         -1.57001-499.747im
         -1.56581-499.079im
         -1.56227-498.703im
         -1.55892-498.436im
         -1.55564-498.228im
         -1.55241-498.056im
          -1.54919-497.91im
           -1.546-497.783im
         -1.54282-497.671im
          -1.53964-497.57im
         -1.53647-497.478im
          -1.5333-497.394im
         -1.53014-497.316im
                          ⋮
           1.53964-497.57im
          1.54282-497.671im
            1.546-497.783im
           1.54919-497.91im
          1.55241-498.056im
          1.55564-498.228im
          1.55892-498.436im
          1.56227-498.703im
          1.56581-499.079im
          1.57001-499.747im
 -1.09504e-10+2.92101e-12im
 -1.09462e-10-3.53962e-11im
In [10]:
for i in [1:length(y)]
    y[i] = complex(y[i],0)
end
In [12]:
Y = Array(Complex, length(y))
for i in [1:length(y)]
    Y[i] = complex(y[i],0)
end
In [13]:
Y
Out[13]:
1000-element Array{Complex{T<:Real},1}:
          0.0+0.0im
   0.00628943+0.0im
    0.0125786+0.0im
    0.0188673+0.0im
    0.0251552+0.0im
    0.0314422+0.0im
    0.0377279+0.0im
    0.0440121+0.0im
    0.0502946+0.0im
     0.056575+0.0im
    0.0628533+0.0im
     0.069129+0.0im
    0.0754021+0.0im
                  ⋮
    -0.069129+0.0im
   -0.0628533+0.0im
    -0.056575+0.0im
   -0.0502946+0.0im
   -0.0440121+0.0im
   -0.0377279+0.0im
   -0.0314422+0.0im
   -0.0251552+0.0im
   -0.0188673+0.0im
   -0.0125786+0.0im
  -0.00628943+0.0im
 -2.44929e-16+0.0im
In [9]:
x = linspace(0, 2pi, 1000)
y = sin(x)
Out[9]:
1000-element Array{Float64,1}:
  0.0        
  0.00628943 
  0.0125786  
  0.0188673  
  0.0251552  
  0.0314422  
  0.0377279  
  0.0440121  
  0.0502946  
  0.056575   
  0.0628533  
  0.069129   
  0.0754021  
  ⋮          
 -0.069129   
 -0.0628533  
 -0.056575   
 -0.0502946  
 -0.0440121  
 -0.0377279  
 -0.0314422  
 -0.0251552  
 -0.0188673  
 -0.0125786  
 -0.00628943 
 -2.44929e-16
In [1]:
f = g = [1:10]
Out[1]:
10-element Array{Int64,1}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
In [2]:
f
Out[2]:
10-element Array{Int64,1}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
In [3]:
g
Out[3]:
10-element Array{Int64,1}:
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
In [6]:
x = 5
[1:x-1]
Out[6]:
4-element Array{Int64,1}:
 1
 2
 3
 4
In [10]:
real(complex(1,-1))
Out[10]:
3
In [11]:
complex(1,-1)
Out[11]:
1 - 1im
In [12]:
real(-1im)
Out[12]:
3
In [13]:
real(-1im)
Out[13]:
3
In [14]:
reset
reset not defined
at In[14]:1
In [15]:
real
Out[15]:
real (generic function with 1 method)
In [16]:
real(-1im)
Out[16]:
3
In [2]:
real(-1im)
Out[2]:
0
In [6]:
foo = Complex[1:10]
Out[6]:
10-element Array{Complex{T<:Real},1}:
  1+0im
  2+0im
  3+0im
  4+0im
  5+0im
  6+0im
  7+0im
  8+0im
  9+0im
 10+0im
In [7]:
foo = Array(Complex, 10)
Out[7]:
10-element Array{Complex{T<:Real},1}:
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
 #undef
In [20]:
exp(1)
Out[20]:
2.7182818284590455
In [21]:
exp( -1im )
Out[21]:
0.5403023058681398 - 0.8414709848078965im
In [22]:
exp( -1im * 2pi )
Out[22]:
1.0 + 2.4492935982947064e-16im
In []: