/* ButterworthIIRDesignerTest.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.AbstractIIRDesigner;
import org.signalml.math.iirdesigner.BadFilterParametersException;
import org.signalml.math.iirdesigner.ButterworthIIRDesigner;
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;
/**
* This class performs unit tests on the {@link ButterworthIIRDesigner} class.
*
* @author Piotr Szachewicz
*/
public class ButterworthIIRDesignerTest {
/**
* an instance of ButterworthIIRDesigner needed to call the tested methods
*/
ButterworthIIRDesigner iirdesigner = new ButterworthIIRDesigner();
/**
* Test method for {@link ButterworthIIRDesigner#designAnalogFilter(org.signalml.math.iirdesigner.FilterType, double[], double[], double, double) }.
*/
@Test
public void testDesignAnalogFilter() throws BadFilterParametersException {
double[] pythonA = new double[] {1.00000000e+00, 1.79338716e+01, 1.60811875e+02,
9.14184873e+02, 3.46464456e+03, 8.32444329e+03, 1.00005000e+04
};
double[] pythonB = new double[] {10000.5000375};
FilterCoefficients coeffs = iirdesigner.designFilter(FilterType.LOWPASS, new double[] {4.0, 0.0}, new double[] {10.0, 0.0}, 3.0, 40.0, true);
FilterCoefficients pyCoeffs = new FilterCoefficients(pythonB, pythonA);
assertEquals(pyCoeffs, coeffs, 1e-4);
}
/**
* Test method for {@link ButterworthIIRDesigner#designDigitalFilter(org.signalml.math.iirdesigner.FilterType, double[], double[], double, double) }.
*/
@Test
public void testDesignDigitalFilter() throws BadFilterParametersException {
double[] pythonB;
double[] pythonA;
FilterCoefficients coeffs;
//lowpass
pythonB = new double[] {1.79924818e-06, 1.25947373e-05, 3.77842118e-05,
6.29736863e-05, 6.29736863e-05, 3.77842118e-05,
1.25947373e-05, 1.79924818e-06
};
pythonA = new double[] {1.0, -5.50239773, 13.10636815,
-17.49826739, 14.12933064, -6.89514162,
1.88178747, -0.22144923
};
coeffs = iirdesigner.designDigitalFilter(FilterType.LOWPASS, new double[] {0.1, 0.0}, new double[] {0.2, 0.0}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-8);
//highpass
pythonB = new double[] {0.0030623, -0.02449839, 0.08574436,
-0.17148872, 0.2143609, -0.17148872,
0.08574436, -0.02449839, 0.0030623
};
pythonA = new double[] {1.00000000e+00, 1.28289711e+00, 1.72596336e+00,
1.13734282e+00, 6.51093826e-01, 2.22784566e-01,
5.74976483e-02, 8.15653354e-03, 5.74611669e-04
};
coeffs = iirdesigner.designDigitalFilter(FilterType.HIGHPASS, new double[] {0.6, 0.0}, new double[] {0.4, 0.0}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-8);
//bandpass
pythonB = new double[] {4.06633016e-04, 0.00000000e+00, -2.43979810e-03,
-9.59124377e-19, 6.09949524e-03, -9.11168158e-18,
-8.13266032e-03, 9.11168158e-18, 6.09949524e-03,
9.59124377e-19, -2.43979810e-03, 0.00000000e+00,
4.06633016e-04
};
pythonA = new double[] {1.00000000e+00, 2.99246806e-16, 3.49439866e+00,
2.70089425e-15, 5.42502143e+00, 4.91071681e-16,
4.68892114e+00, -2.94643009e-15, 2.35792769e+00,
-3.68303761e-16, 6.50028902e-01, 1.61132895e-16,
7.64240933e-02
};
coeffs = iirdesigner.designDigitalFilter(FilterType.BANDPASS, new double[] {0.4, 0.6}, new double[] {0.3, 0.7}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-8);
//bandstop
pythonB = new double[] {7.65853414e-02, 5.23150264e-07, 4.59512048e-01,
2.61575132e-06, 1.14878012e+00, 5.23150264e-06,
1.53170683e+00, 5.23150264e-06, 1.14878012e+00,
2.61575132e-06, 4.59512048e-01, 5.23150264e-07,
7.65853414e-02
};
pythonA = new double[] {1.00000000e+00, 4.16730153e-06, 1.32074661e+00,
5.38773302e-06, 1.43047982e+00, 4.58932829e-06,
7.80068865e-01, 2.02131353e-06, 3.02664538e-01,
5.19781746e-07, 6.15555007e-02, 5.53503535e-08,
5.94651712e-03
};
coeffs = iirdesigner.designDigitalFilter(FilterType.BANDSTOP, new double[] {0.3, 0.7}, new double[] {0.4, 0.6}, 3.0, 40.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-5);
//bandstop 2
pythonB = new double[] {5.06390694e-01, -2.37380515e-07, 5.06390694e-01};
pythonA = new double[] {1.00000000e+00, -2.37380515e-07, 1.27813882e-02};
coeffs = iirdesigner.designDigitalFilter(FilterType.BANDSTOP, new double[] {0.2, 0.8}, new double[] {0.4, 0.6}, 5.0, 10.0);
assertEquals(new FilterCoefficients(pythonB, pythonA), coeffs, 1e-6);
}
/**
* Test method for {@link ButterworthIIRDesigner#calculatePrototype(int) }.
*/
@Test
public void testCalculatePrototype() {
FilterZerosPolesGain zpk1 = iirdesigner.calculatePrototype(3);
Complex[] poles = new Complex[] {new Complex(-0.5, 8.66025404e-1), new Complex(-1.0, 0.0), new Complex(-0.5, -8.66025404e-1)};
FilterZerosPolesGain zpk2 = new FilterZerosPolesGain(new Complex[0], poles, 1.0);
assertEquals(zpk1, zpk2);
}
/**
* Test method for {@link ButterworthIIRDesigner#calculateNaturalFrequency(org.signalml.math.iirdesigner.FilterType, int, double[], double[], double, double, boolean) }.
*/
@Test
public void testCalculateNaturalFrequency() {
//lowpass
double[] result = iirdesigner.calculateNaturalFrequency(FilterType.LOWPASS, 7, new double[] {10}, new double[] {20}, 5, 40, true);
assertEquals(10.359023354921998, result[0], 1e-4);
//digital lowpass
result = iirdesigner.calculateNaturalFrequency(FilterType.LOWPASS, 7, new double[] {0.1}, new double[] {0.2}, 3.0, 40.0, false);
assertEquals(0.10614373313957487, result[0], 1e-4);
//analog highpass
result = iirdesigner.calculateNaturalFrequency(FilterType.HIGHPASS, 4, new double[] {20}, new double[] {10}, 3, 20, true);
assertEquals(17.760467745895387, result[0], 1e-4);
//analog bandstop
result = iirdesigner.calculateNaturalFrequency(FilterType.BANDSTOP, 3, new double[] {1, 4}, new double[] {2, 3}, 3, 20, true);
assertEquals(1.59974742, result[0], 1e-4);
assertEquals(3.75058475, result[1], 1e-4);
//analog bandpass
result = iirdesigner.calculateNaturalFrequency(FilterType.BANDPASS, 11, new double[] {2, 4}, new double[] {1, 5}, 5.0, 50.0, true);
assertEquals(1.99511416, result[0], 1e-8);
assertEquals(4.00979561, result[1], 1e-8);
//digital bandpass
result = iirdesigner.calculateNaturalFrequency(FilterType.BANDPASS, 9, new double[] {0.2, 0.4}, new double[] {0.1, 0.5}, 5.0, 50.0, false);
assertEquals(0.19975973, result[0], 1e-8);
assertEquals(0.40038904, result[1], 1e-8);
}
/**
* Test method for {@link ButterworthIIRDesigner#calculateFilterOrder(org.signalml.math.iirdesigner.FilterType, double[], double[], double, double, boolean) }.
*/
@Test
public void testCalculateFilterOrder() throws BadFilterParametersException {
//lowpass
int filterOrder = iirdesigner.calculateFilterOrder(FilterType.LOWPASS, new double[] {10, 0.0}, new double[] {20, 0.0}, 5, 40, true);
assertEquals(7, filterOrder);
//digital lowpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.LOWPASS, 0.1, 0.2, 3.0, 40.0, false);
assertEquals(7, filterOrder);
//highpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.HIGHPASS, new double[] {20, 0.0}, new double[] {10, 0.0}, 3, 20, true);
assertEquals(4, filterOrder);
//bandstop
filterOrder = iirdesigner.calculateFilterOrder(FilterType.BANDSTOP, new double[] {1, 4}, new double[] {2, 3}, 3, 20, true);
assertEquals(3, filterOrder);
//bandpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.BANDPASS, new double[] {2, 4}, new double[] {1, 5}, 5.0, 50.0, true);
assertEquals(11, filterOrder);
//digital bandpass
filterOrder = iirdesigner.calculateFilterOrder(FilterType.BANDPASS, new double[] {0.2, 0.4}, new double[] {0.1, 0.5}, 5.0, 50.0, false);
assertEquals(9, filterOrder);
}
/**
* Test method for {@link ButterworthIIRDesigner#calculateBandstopObjectiveFunctionValue(double, int, double[], double[], double, double) }.
*/
@Test
public void testBandstopObjectiveFunction() {
//butterworth test
AbstractIIRDesigner.BandstopObjectiveFunction bo = iirdesigner.new BandstopObjectiveFunction(0,
new double[] {0.5, 0.8},
new double[] {0.6, 0.7},
3, 40);
assertEquals(-3.546182557211913, bo.value(1.0), 1e-8);
//butterworth test 2
bo = iirdesigner.new BandstopObjectiveFunction(0,
new double[] {1.0, 4.0},
new double[] {2.0, 3.0},
3, 20);
assertEquals(7.9947088019182813, bo.value(0.0), 1e-8);
assertEquals(14.920040569147393, bo.value(1.9), 1e-8);
//butterworth test 3
bo = iirdesigner.new BandstopObjectiveFunction(0, new double[] {1.0, 4.0}, new double[] {2.0, 3.0}, 3, 20);
//double wp0 = SpecialMath.minimizeFunctionConstrained(objectiveFunction, 1.0, 2.0-1e-12);
assertEquals(2.5100487397489273, bo.value(1.5), 1e-4);
}
}