/* EllipticIIRDesignerTest.java created 2010-09-12
*
*/
package org.signalml.math.iirdesigner;
import org.apache.commons.math.complex.Complex;
import static org.signalml.math.iirdesigner.IIRDesignerAssert.*;
import org.junit.Test;
import java.lang.Math.*;
import org.signalml.math.iirdesigner.BadFilterParametersException;
import org.signalml.math.iirdesigner.EllipticIIRDesigner;
import org.signalml.math.iirdesigner.FilterCoefficients;
import org.signalml.math.iirdesigner.FilterType;
import org.signalml.math.iirdesigner.FilterZerosPolesGain;
import org.signalml.math.iirdesigner.AbstractIIRDesigner.BandstopObjectiveFunction;
import org.signalml.math.iirdesigner.EllipticIIRDesigner.KRatio;
import org.signalml.math.iirdesigner.EllipticIIRDesigner.VRatio;
/**
* This class performs unit tests on {@link EllipticIIRDesigner} class.
* @author Piotr Szachewicz
*/
public class EllipticIIRDesignerTest {
/**
* an instance of {@link EllipticIIRDesigner} needed to call all the tested methods.
*/
EllipticIIRDesigner iirdesigner = new EllipticIIRDesigner();
/**
* Test method for {@link EllipticIIRDesigner#designDigitalFilter(org.signalml.math.iirdesigner.FilterType, double[], double[], double, double) }.
*/
@Test
public void testDesignDigitalFilter() throws BadFilterParametersException {
double[] pythonB;
double[] pythonA;
FilterCoefficients coeffs;
//lowpass test
pythonB = new double[] {0.00881574, -0.00485172, -0.00485172, 0.00881574};
pythonA = new double[] {1.0, -2.74146002, 2.58002871, -0.83064064};
coeffs = iirdesigner.designFilter(FilterType.LOWPASS, new double[] {0.1}, new double[] {0.2}, 3.0, 40.0, false);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-5);
//highpass
pythonB = new double[] {0.04105714, -0.05209928, 0.05209928, -0.04105714};
pythonA = new double[] {1.0, 1.85768178, 1.61734402, 0.57334941};
coeffs = iirdesigner.designDigitalFilter(FilterType.HIGHPASS, new double[] {0.7}, new double[] {0.3}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-4);
//bandpass test
pythonB = new double[] {0.02114251, 0.01792455, -0.00243741,
0.0, 0.00243741, -0.01792455, -0.02114251
};
pythonA = new double[] {1.0, 1.73921561, 3.38814582,
3.10556401, 3.01265939, 1.35579533, 0.69028645
};
coeffs = iirdesigner.designDigitalFilter(FilterType.BANDPASS, new double[] {0.5, 0.7}, new double[] {0.3, 0.9}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-4);
//bandstop test
pythonB = new double[] {0.0987149, 0.16661581, 0.31652632,
0.30320545, 0.31652632, 0.16661581,
0.0987149
};
pythonA = new double[] {1.0, 0.68543316, -0.66268689,
0.05276535, 0.9103521, -0.10176143,
-0.41718278
};
coeffs = iirdesigner.designDigitalFilter(FilterType.BANDSTOP, new double[] {0.3, 0.9}, new double[] {0.5, 0.7}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-4);
}
/**
* Test method for {@link VRatio#function(double[]) }.
*/
@Test
public void testVRatioFunction() {
EllipticIIRDesigner.VRatio vRatio = new VRatio(0.1, 0.2);
assertEquals(0.44117773230576596, vRatio.value(0.5), 1e-16);
}
/**
* Test method for {@link KRatio#function(double[]) }.
*/
@Test
public void testKRatioFunction() {
EllipticIIRDesigner.KRatio kRatio = new KRatio();
kRatio.setKRatio(0.3);
assertEquals(0.69999999999999996, kRatio.value(0.5), 1e-16);
kRatio.setKRatio(-0.3);
assertEquals(0.29999999999999999, kRatio.value(1.5), 1e-16);
kRatio.setKRatio(0.6);
assertEquals(0.40000000000000002, kRatio.value(0.5), 1e-16);
}
/**
* Test method for {@link EllipticIIRDesigner#calculatePrototype(int, double, double) }.
*/
@Test
public void testCalculatePrototype() throws BadFilterParametersException {
//filterOrder=1
FilterZerosPolesGain zpk1 = iirdesigner.calculatePrototype(1, 2, 3);
FilterZerosPolesGain zpk2 = new FilterZerosPolesGain(new Complex[0], new Complex[] {new Complex(-1.3075602715790791, 0.0)}, 1.3075602715790791);
assertEquals(zpk1, zpk2);
//another test (even filter order)
zpk1 = iirdesigner.calculatePrototype(4, 2, 3);
Complex[] zeros = new Complex[] {new Complex(0, 1.06863478), new Complex(0, -1.06863478), new Complex(0, 1.00007796), new Complex(0, -1.00007796)};
Complex[] poles = new Complex[] {new Complex(-6.62726745e-02, -1.00672153), new Complex(-6.62726745e-02, +1.00672153), new Complex(-7.22990126e-05, -1.00001461), new Complex(-7.22990126e-05, 1.00001461)};
double gain = 0.70791820787954829;
zpk2 = new FilterZerosPolesGain(zeros, poles, gain);
//assertEquals(zpk1, zpk2, 1e-1);
//odd filter order
zpk1 = iirdesigner.calculatePrototype(5, 3, 40);
zeros = new Complex[] {new Complex(0, 1.58139008), new Complex(0, -1.58139008), new Complex(0, 1.16628458), new Complex(0, -1.16628458)};
poles = new Complex[] {new Complex(-0.25129106, 0), new Complex(-0.13168110, -0.74196202), new Complex(-0.13168110, 0.74196202), new Complex(-0.02642856, -0.98568577), new Complex(-0.02642856, 0.98568577)};
gain = 0.040785969129633996;
zpk2 = new FilterZerosPolesGain(zeros, poles, gain);
}
/**
* Test method for {@link EllipticIIRDesigner#calculateBandstopObjectiveFunctionValue(double, org.signalml.math.iirdesigner.AbstractIIRDesigner.BandstopObjectiveFunction) }.
*/
@Test
public void testBandstopObjectiveFunction() {
//elliptic test
BandstopObjectiveFunction bo = iirdesigner.new BandstopObjectiveFunction(0,
new double[] {0.1, 0.8}, new double[] {0.4, 0.6}, 3, 20);
assertEquals(2.4835659582481822, bo.value(0.0), 1e-8);
//elliptic test 2
bo = iirdesigner.new BandstopObjectiveFunction(0,
new double[] {0.5, 0.8}, new double[] {0.55, 0.7}, 0.5, 100);
assertEquals(11.571836975873939, bo.value(0.00), 1e-4);
//elliptic test 3
bo = iirdesigner.new BandstopObjectiveFunction(0,
new double[] {0.5, 0.8}, new double[] {0.55, 0.7}, 2.5, 130);
assertEquals(12.802279159652183, bo.value(0.09), 1e-4);
}
/**
* Test method for {@link EllipticIIRDesigner#calculateNaturalFrequency(org.signalml.math.iirdesigner.FilterType, int, double, double, double, double, boolean) }.
*/
@Test
public void testCalculateNaturalFrequency() throws BadFilterParametersException {
double[] wn;
//test 1
wn = iirdesigner.calculateNaturalFrequency(FilterType.BANDPASS, 7, new double[] {0.6, 0.7}, new double[] {0.55, 0.8}, 0.5, 100, true);
assertEquals(new double[] {0.6, 0.7}, wn, 1e-16);
//test 2
wn = iirdesigner.calculateNaturalFrequency(FilterType.BANDSTOP, 3, new double[] {0.3, 0.9}, new double[] {0.5, 0.7}, 3.0, 40.0, true);
assertEquals(new double[] {0.38888824, 0.89999518}, wn, 1e-4);
//test 3
wn = iirdesigner.calculateNaturalFrequency(FilterType.BANDSTOP, 3, new double[] {0.3, 0.9}, new double[] {0.5, 0.7}, 3.0, 40.0, false);
assertEquals(new double[] {0.30000218, 0.83829193}, wn, 1e-5);
//test 4
wn = iirdesigner.calculateNaturalFrequency(FilterType.BANDSTOP, 8, new double[] {0.5, 0.8}, new double[] {0.55, 0.7}, 0.5, 100, true);
assertEquals(new double[] {0.50000531, 0.7699937}, wn, 1e-5);
}
/**
* Test method for {@link EllipticIIRDesigner#calculateFilterOrder(org.signalml.math.iirdesigner.FilterType, double[], double[], double, double, boolean) }.
*/
@Test
public void testCalculateFilterOrder() throws BadFilterParametersException {
int filterOrder;
//digital lowpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.LOWPASS, 0.4, 0.7, 3, 40, false);
assertEquals(3, filterOrder);
//digital highpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.HIGHPASS, 0.7, 0.3, 1, 80, false);
assertEquals(5, filterOrder);
//digital bandstop
filterOrder = iirdesigner.calculateFilterOrder(FilterType.BANDSTOP, new double[] {0.5, 0.8}, new double[] {0.6, 0.7}, 0.5, 100, false);
assertEquals(6, filterOrder);
//analog bandpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.BANDPASS, new double[] {0.6, 0.7}, new double[] {0.55, 0.8}, 0.5, 100, true);
assertEquals(7, filterOrder);
}
}