Re: spectral energy from 2D FFT

From: Dennis Shea <shea_at_nyahnyahspammersnyahnyah>
Date: Fri Feb 12 2010 - 10:53:56 MST

NCL uses:

fft2df:
http://www.cisl.ucar.edu/css/software/fftpack5/rfft2f.html

fft2db:
http://www.cisl.ucar.edu/css/software/fftpack5/rfft2b.html

========

I wrote the attached test script.
The function pair fft2df <==> fft2db work in the sense
that the original array can be reconstructed from the derived coefficients.

However, I also can not figure out how to get the variance from
these coefficients. The coefficients are normalized. Sometimes
a sqrt(2), sqrt(2/pi), sqrt(pi), etc or some such coefficient
can be used but I just can not seem to determine anything that works.

Attached is a simple test script.

=========
Ideas anyone???

=======
Note:
http://www.ncl.ucar.edu/Document/Functions/Contributed/wave_number_spc.shtml

"wave_number_spc" requires a global grid.
It uses spherical harmonics to (hopefully) get the wave number spectrum.

You can see the code by:

%> less contributed.ncl

Then search for wave_number_spc

====

An example that uses fft2df

http://www.ncl.ucar.edu/Applications/twoPointCor.shtml

=====

Good luck

Bjoern Maronga wrote:
> I have problems carrying out proper spectra from a discrete two-dimensional
> field A (e.g. vertical velocity). Unfortunately, NCL does not support the
> function ezfft2f yet. So I was trying to use fft2df for a 2D-FFT. Following
> literature (e.g. Stull), the variance of my field A should be equal to the
> sum of square of the norm of the Fourier transform F_A:
>
> variance(A) = sum from i=1 to N-1 of | F_A(i) |^2
> where | F_A(i) |^2 = (F_Arealpart(i)^2 + F_Aimag.part(i)^2
>
> for a 1D series. I tried to use this to check whether the FFT is working
> properly. But I am confused. The equation should adapted to 2D be:
>
> variance(A) = sum from i=1 to N-1 sum from j=1 to N-1 of | F_A(i,j) |^2
> where | F_A(i,j) |^2 = (F_Arealpart(i,j)^2 + F_Aimag.part(i,j)^2
>
> But the results are quite different (0.265 and 0.48). The function fft2df
> transforms the array A(M x N) to an array of size (M x N/2+1). Now I'm not
> sure, how to sum up to get correct variances. I tried summing up the full
> array as well as only (N/2+1,N/2+1) and cared for the mean values in i=0 and
> j=0.
>
> Furthermore I want to calculate the variance (energy) spectrum from the
> Fourier transform F_A and plot variance against wave number, in consideration
> of the grid spacing of 100m in the original data.
>
> I haven't found any useful information about how to handle the FFT result of a
> 2D field and how to carry out the desired spectrum.
>
> Has anybody a solution or hints?
>
> Best regards,
> Bjoern Maronga
> _______________________________________________
> ncl-talk mailing list
> List instructions, subscriber options, unsubscribe:
> http://mailman.ucar.edu/mailman/listinfo/ncl-talk

      M = 2
      L = 6 ; fastest varying dimension
      x = new ( (/M,L/), "float")
      x(0,0) = 0.968
      x(0,1) = 0.067
      x(0,2) = 0.478
      x(0,3) = 0.910
      x(0,4) = 0.352
      x(0,5) = 0.933

      x(1,0) = 0.654
      x(1,1) = 0.021
      x(1,2) = 0.512
      x(1,3) = 0.202
      x(1,4) = 0.940
      x(1,5) = 0.204

      N = M*L
                                     ; [re/im] [M] [L/2+1]
      coef = fft2df (x) ; [2] x [2] x [4]
      xNew = fft2db(coef)
      print("---")
      print("x="+x+" xNew="+xNew)

      epsx = 0.00001 ; make sure transforms work
      if (any(xNew.lt.(x-epsx) .or. xNew.gt.(x+epsx))) then
          print("fft2df <==> fft2db: something wrong")
          exit
      end if

      print("---")
      print("coef: "+coef)

      do m=0,M-1
         print("---> m="+m)
         print("coef(real): "+coef(0,m,:)+" coef(imag)="+coef(1,m,:))
      end do

      avgx = avg(x) ; overall average
      print("---")
      print("avg(x)="+avgx+" coef(0,0,0)="+coef(0,0,0))

      varxs = variance(x) ; overall sample (unbiased) variance
      varxp = (variance(x)*(N-1))/N ; overall population variance

      coef2 = coef(:,:,1:)^2 ; *ignore* the (:,:,0) coef
      varc2 = sum(coef2) ; variance
      print("---")
      print("varc2="+varc2+" varxp="+varxp+" varxs="+varxs)

             ; real imag
      varcri = sum(coef(0,:,1:)^2 + coef(1,:,1:)^2)
      print("---")
      print("varcri="+varcri)

      print("---")
      print("varc2/sqrt(2)="+varc2/sqrt(2))

      print("---")
      print("varc2/sqrt(pi)="+varc2/sqrt(3.14159))

      print("---")
      print("varc2/sqrt(pi/2)="+varc2/sqrt(3.14159/2))

      print("---")
      print("varc2/(pi/2)="+varc2/(3.14159/2))

      print("---")
      print("varc2/(sqrt(pi)/2)="+varc2/(sqrt(3.14159)/2))

                                       ; partition by component
      avgM = dim_avg(x) ; avg for each M
      varM = (dim_variance(x)*(L-1))/L ; population variance for each M
      print("---")
      print("avgM="+avgM+" varM="+varM)

_______________________________________________
ncl-talk mailing list
List instructions, subscriber options, unsubscribe:
http://mailman.ucar.edu/mailman/listinfo/ncl-talk
Received on Fri Feb 12 10:54:02 2010

This archive was generated by hypermail 2.1.8 : Thu Feb 18 2010 - 10:33:29 MST