0

I'm working with a basic example of FFT with Apache Commons library. I have two classes:

   public class Fourier {
    private static XYSeries data;
    private static XYSeriesCollection collection;

    Fourier(){
        collection =new XYSeriesCollection();
        createSquare();
        createFourier();
        showGraph();
    }

    private static void createSquare(){
        data=new XYSeries("Dati");
        for(double i=-8;i<8;i+=1d/128){
            data.add(i,((i<-4||(i<4&&i>0)?1:0)));
            //data.add(i,(i<0?i+1:-i+1));
        }
        collection.addSeries(data);
    }

    private static void createFourier(){
        double[] arrayFourier= new double[data.getItemCount()];
        for(int i=0;i<data.getItemCount();i++){
            arrayFourier[i]=data.getDataItem(i).getYValue();
        }
        FastFourierTransformer transformer=new FastFourierTransformer(DftNormalization.STANDARD);
        Complex[] coeff=transformer.transform(arrayFourier, TransformType.INVERSE);
        double norm = 0;
        for(Complex Z: coeff){
            System.out.println(Z.abs()+"\t"+Z.toString());
            norm+=(Z.abs())*(Z.abs());
        }
        System.out.println(norm);

        XYSeries fourier=new XYSeries("Fourier");
        FourierSeries series=new FourierSeries(coeff,8);
        for(double i=data.getMinX();i<data.getMaxX();i+=0.05){
            fourier.add(i,series.getSeries(i));
        }
        collection.addSeries(fourier);

    }

    private static void showGraph(){
        JFreeChart chart = ChartFactory.createXYLineChart("Fourier", "x", "f(x)", collection, PlotOrientation.VERTICAL, true, false, false);
        ChartFrame window=new ChartFrame("Fourier", chart, false);
        window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        window.pack();
        window.setVisible(true);
    }

    public static void main(String[] args) {
        Thread t=new Thread(new Runnable() {

            @Override
            public void run() {
                new Fourier();
                try {
                    Thread.sleep(60000);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.exit(0);
            }
        });
        t.start();
    }

}

and another one

public class FourierSeries {
    Complex[] coeff;
    double T;

    public FourierSeries(Complex[] coeff, double T) {
        this.coeff=coeff;
        this.T=T;
    }

    public double getSeries(double x){
        double k=Math.PI/T;
        double value=0; //primo coefficiente
        int i=0;
        /*for(Complex iter:coeff){
            if (i!=0&&i<coeff.length/2.) {
                if (i % 2 == 0) {
                    value += iter.abs() * Math.cos(k * i * x);
                    System.out.println(iter.abs()+"cos"+i);
                } else {
                    value += iter.abs() * Math.sin(k * i * x); //npari (i dispari) modulo*cos()
                    System.out.println(iter.abs()+"sin"+i);
                }
            }
            i++;
        }*/
        for (Complex iter : coeff) {
            if(i<coeff.length/2.)   
            value+=iter.getReal()*Math.cos(x*k*i)+iter.getImaginary()*Math.sin(x*k*i);
        i++;
        }
        return value;
    }
}

I introduce in my createSquare() method a function (square wave).

In order I do the following actions:

I perform the FFT.

Can you explain me how the array returned by transform.transform(array, TransformType) is composed?

Why the Fourier series is not correctly drawn?

The inverse series is correctly a square wave with same frequency as initial wave, but not correctly scaled on y-axsis. What is wrong? This is the output: This is the output

trashgod
  • 203,806
  • 29
  • 246
  • 1,045
Phil
  • 115
  • 1
  • 11
  • Please edit your question to include a [mcve] that exhibits the problem you describe. – trashgod Nov 24 '16 at 00:29
  • 3
    maybe this related QA will help: [How to compute Discrete Fourier Transform?](http://stackoverflow.com/a/26355569/2521214) my bet is that you forget to multiply the result with normalization constant but too lazy to analyze your code ... – Spektre Nov 24 '16 at 07:56

1 Answers1

2

In transforming the complex form of the Fourier series to the real form, you have to treat the constant term differently. Or in the case of the code in question, you have to correct the non-constant coefficients by a factor of 2. So that you get 0.5 +- 0.5 as result, not 0.5 +- 0.25 as is currently the case.

You are using the inverse transform, where the resulting coefficients can then be interpreted as

f(x) approx sum(m = -N/2+1, N/2-1) c[k]*exp(-i*m*k*x)

For index m>=1 you combine two complex conjugate pairs of terms, the resulting real terms are, using c[k]=a+ib,

(a+i*b)*exp(-i*m*k*x) + (a-i*b)*exp(+i*m*k*x) 

= 2*a*cos(m*k*x) + 2*b*sin(m*k*x)

Your Fourier series computation should thus look like

    value = coeff[0].getReal();
    for (int m=1; m<coeff.length/2; m++) {
        value += 2*coeff[m].getReal()*Math.cos(x*k*m) 
               + 2*coeff[m].getImaginary()*Math.sin(x*k*m);
    }
Lutz Lehmann
  • 25,219
  • 2
  • 22
  • 51
  • This worked for me, but with a minus in value overall! – Phil Nov 24 '16 at 17:30
  • Reverse the sign before the sinus. As you are using the inverse transform, the exponential factors have both to be negated. -- Changed it in the answer. – Lutz Lehmann Nov 24 '16 at 17:54