Fast Fourier transform, how to work with complex numbers if there are none

using System.Numerics;

namespace BPF
{
    public static class danie
    {
        public static Complex[] X;
        public static Complex[] Y;

        public static Complex[] FastPFurie;

    }
    class Program
    {
        static void Main(string[] args)
        {

            danie.X = GetDan("exaX.txt");
            danie.Y = GetDan("exa.txt");
            FFT ff = new FFT();
            danie.FastPFurie=FFT.fft(danie.X);
            Form1 f = new Form1();
            f.ShowDialog();
            Console.ReadKey();
        }
        public static int n = 0;


        public static Complex[] GetDan(string fail)//получение данных из файла
        {
            n = 0;
            string s = "";
            StreamReader r = new StreamReader(fail);
            s = r.ReadLine();
            n = s.Split(' ').Length;
            Complex[] matrix = new Complex[n];
            string[] l = s.Split(' ');
            for (int k = 0; k < n; k++)
            {
                matrix[k] = Convert.ToDouble(l[k]);
            }
            r.Close();
            return matrix;
        }
    }

}

-

public class FFT
{
    /// Вычисление поворачивающего модуля e^(-i*2*PI*k/N)

    private static Complex w(int k, int N)
    {
        if (k % N == 0) return 1;
        double arg = -2 * Math.PI * k / N;
        return new Complex(Math.Cos(arg), Math.Sin(arg));
    }

    /// Возвращает спектр сигнала

    /// <param name="x">Массив значений сигнала. Количество значений должно быть степенью 2</param>
    /// <returns>Массив со значениями спектра сигнала</returns>
    public static Complex[] fft(Complex[] x)
    {
        Complex[] X;
        int N = x.Length;
        if (N == 2)
        {
            X = new Complex[2];
            X[0] = x[0] + x[1];
            X[1] = x[0] - x[1];
        }
        else
        {
            Complex[] x_even = new Complex[N / 2];
            Complex[] x_odd = new Complex[N / 2];
            for (int i = 0; i < N / 2; i++)
            {
                x_even[i] = x[2 * i];
                x_odd[i] = x[2 * i + 1];
            }
            Complex[] X_even = fft(x_even);
            Complex[] X_odd = fft(x_odd);
            X = new Complex[N];
            for (int i = 0; i < N / 2; i++)
            {
                X[i] = X_even[i] + w(i, N) * X_odd[i];
                X[i + N / 2] = X_even[i] - w(i, N) * X_odd[i];
            }
        }
        return X;
    }
    /// <summary>
    /// Центровка массива значений полученных в fft (спектральная составляющая при нулевой частоте будет в центре массива)
    /// </summary>
    /// <param name="X">Массив значений полученный в fft</param>
    /// <returns></returns>
    public static Complex[] nfft(Complex[] X)
    {
        int N = X.Length;
        Complex[] X_n = new Complex[N];
        for (int i = 0; i < N / 2; i++)
        {
            X_n[i] = X[N / 2 + i];
            X_n[N / 2 + i] = X[i];
        }
        return X_n;
    }
}

The files contain the values of the ecg signal: 26,48 24,743 19,478 18,407 20,252 23,051 21,028.... and so on, this is a calculation by Y, by X in another file, after the transformations, it gives a miracle graph...

public Form1()
    {
        InitializeComponent();
        chart1.Series[0].ChartType = SeriesChartType.Spline;
        chart2.Series[0].ChartType = SeriesChartType.Spline;
    }

    private void button1_Click(object sender, EventArgs e)
    {
        foreach (Complex complex in danie.FastPFurie)
            chart1.Series[0].Points.AddXY(complex.Real, complex.Imaginary);
    }

enter a description of the image here

 0
Author: Михаил Ребров, 2018-11-30

2 answers

The result of the FFT is an array of complex amplitudes. It is pointless to take the real and imaginary parts from it, since only the module carries useful information (from the point of view of signal analysis). Plotting a graph should look something like this:

for (int i=0; i < danie.FastPFurie.Length; i++) {
    chart1.Series[0].Points.AddXY(i, Complex.Abs(danie.FastPFurie[i]));
}
 0
Author: MSDN.WhiteKnight, 2018-11-30 15:49:36

For fft, we need uniform samples, i.e. an array Y with a constant step in X. The data is entered in the real part, the imaginary part is filled with zeros.

After the conversion, you can display the amplitude of the complex numbers. For some purposes, you may also need a phase.

And not only everyone can watch the imaginary and real part. Few people can do this ©

To begin with, you should practice on obviously understandable data - for example, fill the array with a sine or sum multiple sinuses with different frequencies - the amplitude graph should have large peaks in the number of frequencies (if the frequencies fall within the range), and a bunch of small peaks.

 0
Author: MBo, 2018-11-30 15:49:01