package net.heartshield.filter;

import junit.framework.TestCase;

import net.heartshield.signal.DVec;
import net.heartshield.signal.Series;
import net.heartshield.signal.Signal;

import org.apache.commons.math3.util.MathArrays;
import org.jfree.data.xy.XYSeries;
import uk.me.berndporr.iirj.*;

/**
 * @author David Madl (git@abanbytes.eu)
 * @date 2017-05-14
 */
public class IirTests extends TestCase {

    public void testButterSweep() {
        /*
        fps = 2e3
        T = 10.0
        t = np.linspace(0, T, int(T * fps))
        fs = np.logspace(0, np.log10(fps/2.0), int(T * fps))
        sweep = np.cos(2*np.pi*fs*t)
        
        with open('/mnt/hsh/protos/dha3/data/butter_sweep.json', 'w') as fo:
            fo.write(json.dumps({'t': list(t), 'x': list(sweep)}))
         */
        Series series = new Series("data/butter_sweep.json");

        double FPS = 48000.0;

        double[] arr = series.x;
        //double[] filtered = out.getData();
        double[] filtered = new double[arr.length];


        Butterworth butterworth = new Butterworth();
        int order = 3;
        butterworth.lowPass(order, FPS, 4000.0);



        long t1 = System.nanoTime();
        for(int j = 0; j < arr.length; j++) {
            //System.out.println(j + " " + filtered[j]);

            filtered[j] = butterworth.filter(arr[j]);
        }
        long t2 = System.nanoTime();

        // 7, 3, 5, 2.7, 3.7 ms   -> roughly 3 ms
        System.out.println("filtering " + arr.length + " points took " + (t2-t1) + " ns");

        if(filtered.length != arr.length)
            throw new IllegalStateException("output.length != input.length");


        final XYSeries inSeries = new XYSeries("input");
        final XYSeries outSeries = new XYSeries("output");

        for(int j = 0; j < arr.length; j++) {
            inSeries.add(j, arr[j]);
            outSeries.add(j, filtered[j]);
        }

        LineChart lc = new LineChart("filter", new XYSeries[]{ outSeries, inSeries });

        //LineChart lc = LineChart.plot(filtered);
        lc.showChart();
        lc.waitChart();
    }

    public void testLowPass() {

        Series series = new Series("data/butter_sweep.json");

        double FPS = 2000.0;

        double[] arr = series.x;


        LowPassFilter lowPass = new LowPassFilter(FPS, 100.0, 50.0);
        DataSink out = new DataSink();
        lowPass.connect(out);

        long t1 = System.nanoTime();
        for(int i = 0; i < arr.length; i += 200)
            lowPass.put(DVec.get(arr, i, i + 200));
        //lowPass.put(arr);
        long t2 = System.nanoTime();
        double[] filtered = out.getData();

        System.out.println("filtering " + arr.length + " points took " + (t2-t1) + " ns");



        if(filtered.length != arr.length)
            throw new IllegalStateException("output.length=" + filtered.length + " != input.length=" + arr.length);


        final XYSeries inSeries = new XYSeries("input");
        final XYSeries outSeries = new XYSeries("output");

        for(int j = 0; j < arr.length; j++) {
            inSeries.add(j, arr[j]);
            outSeries.add(j, filtered[j]);
        }

        // tw=10 -> 76 ms, 81 ms, 67 ms  (but sharper)
        // strange that raising tw does not seem to change much?!  aah, chunk size...
        LineChart lc = new LineChart("filter", new XYSeries[]{ outSeries, inSeries });

        //LineChart lc = LineChart.plot(filtered);
        lc.showChart();
        lc.waitChart();

    }

    public static double[] convolve(double[] f, double[] g) {
        //double[] y = new double[f.length];
        double[] y = MathArrays.convolve(f, g);
        return DVec.get(y, g.length/2, y.length - g.length/2 + 1);
    }

    public void testConvolve() {

        Series series = new Series("data/butter_sweep.json");

        double FPS = 2000.0;

        double[] arr = series.x;

        double[] tri = Signal.triangle(400);

        long t1 = System.nanoTime();
        double[] filtered = convolve(arr, tri);
        long t2 = System.nanoTime();


        System.out.println("filtering " + arr.length + " points took " + (t2-t1) + " ns");



        if(filtered.length != arr.length)
            throw new IllegalStateException("output.length=" + filtered.length + " != input.length=" + arr.length);


        final XYSeries inSeries = new XYSeries("input");
        final XYSeries outSeries = new XYSeries("output");

        for(int j = 0; j < arr.length; j++) {
            inSeries.add(j, arr[j]);
            outSeries.add(j, filtered[j]);
        }

        // 50 ms-ish.
        // note: can do with half the triangle length, will be faster then. -> 37, 32 ms
        LineChart lc = new LineChart("filter", new XYSeries[]{ outSeries, inSeries });

        //LineChart lc = LineChart.plot(filtered);
        lc.showChart();
        lc.waitChart();

    }
}
