3
$\begingroup$

I have recently started to use MathNet.Numerics, and one of my needs is to perform FFT analysis of Electromyographical signals.

The first test I did was to get some 15 seconds of signals at 2kHz, this is how it plots:

enter image description here

I have a Python script I wrote some time ago, and the FFT spectrum generated is below:

lenfft = len(signal)/2.
nyq = 2000/2.
freq_axis = numpy.linspace(0, nyq, lenfft+1)
spectrum = numpy.abs(numpy.fft.rfft(signal))
plt.plot(freq_axis, spectrum)
plt.show()

enter image description here

The problem is, when I use MathNet.Numerics, I get a weird result (code and image below):

Complex[] signal = ArrayOfDoublesFromFile()
                        .Select(val => new Complex(val, 0))
                        .ToArray();

Fourier.Forward(signal, FourierOptions.Default); // inplace

SaveToFile(signal);

enter image description here

I know that if the inputs are pure real numbers, the output should be symmetrical or something like that, but since Fourier.Forward() requires a MatNet.Numerics.Complex[] array, I am creating an array with imaginary part set to zero, and also using only real part of result for plotting, is that correct?

So, the question is: whats the meaning of the output generated by MathNet.Numerics.Fourier.Forward(), and what should I make if I want a result in the visual form most commonly associated with FFT, that is, the middle figure?

$\endgroup$
2
$\begingroup$

Note the symmetry in your 3rd plot. That tells me the MathNet.Numerics FFT is computing a full-frequency FFT (both positive and negative frequencies), and plotting the FFT results where zero Hz should be the center of the horizontal axis. However, Problem# 1, for some reason the labeling of the horizontal axis does NOT have zero Hz in the center. I can’t explain that. Problem# 2, there’s something very wrong with the ‘flat-top’ spectral shape in your 3rd plot. Problem# 3, it seems impossible to me that your 3rd plot should have spectral components whose magnitudes are 10 raised to the 15th power. (Looking at your 1st plot I’d expect your spectral magnitude results to be on the order of 10 raised to the 7th power.) Stated in technical terms, your 3rd plot is “truly FUBAR.”

The answer, heltonbiker, is for you to determine precisely, in great detail, EXACTLY what processing is taking place in your MathNet.Numerics FFT and plotting routines. Good Luck.

$\endgroup$
  • $\begingroup$ Thanks for your answer, I have already ditched MathNet.Numerics for this specific application - quite infortunately, I have to say... $\endgroup$ – heltonbiker Sep 16 '15 at 13:05
0
$\begingroup$

Typically for spectral analysis, the magnitude is plotted of the fft output. Hence the absolute value of the fft output is taken in your example python code. The maths behind the fft expect the input to be complex but we usually input only real values, but this is OK. By outputting only the real, you're only looking at the energy estimate in the cosine waves that comprising your signal whilst ignoring the sines. The magnitude is the square root, of the sum, of the squares (of both real and imaginary parts).

$\endgroup$
0
$\begingroup$

for those who faced same problem with math.net. in the future

1) after you got your fourier result/output, instead of this:

var nth_Val = signal[i].real  ;  // this is wrong 

use this:

var nth_Val = signal[i].Magnitude          ; // real amplitude  

even though you send input with imaginary part 0.0 value. the output contains imaginary parts you need to square_root( real^2 + imaginary^2 ) or use maqnitude which is same .


if 1st option doesnt work do this:

2) forward was giving even level amplitudes . so i used inverse. that gave me better result for audio peak amplitude.

 Fourier.Inverse( fftData, FourierOptions.Matlab );

my complete snippet

  var fftData = new  Complex[  44100 ];  //(int) Math.Pow( 2,16)
  for (int i = 0; i < fftData.Length ; ++i)
  {
     // Fill the complex data
     fftData[i] = new Complex( data[ 1300 + i ] , 0 ) ; 
  }

  // FFT the time domain data to get frequency domain data
  Fourier.Inverse( fftData, FourierOptions.Matlab );

  //fftData now has results. but it contains "result+result_mirror"
  // so we take the first half of fftData
  var result = fftData
                  .Select( x => x.Magnitude )
                  .Take(fftData.Length / 2).ToArray();     
$\endgroup$
  • $\begingroup$ Doing an inverse transform to go from time to frequency seems wrong to me $\endgroup$ – Mike Dinescu Aug 7 at 7:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.