package org.signalml.domain.signal.filter.iir;
import static org.junit.Assert.assertEquals;
import static org.signalml.SignalMLAssert.assertArrayEquals;
import org.junit.Test;
import org.signalml.domain.signal.filter.TestingSignals;
import org.signalml.domain.signal.filter.iir.AbstractIIRSinglechannelSampleFilter;
import org.signalml.domain.signal.filter.iir.OnlineIIRSinglechannelSampleFilter;
import org.signalml.domain.signal.samplesource.ChannelSelectorSampleSource;
import org.signalml.domain.signal.samplesource.MultichannelSampleSource;
import org.signalml.math.iirdesigner.FilterCoefficients;
/**
* This class performs unit tests on the {@link OnlineIIRSinglechannelSampleFilter} class.
*
* @author Piotr Szachewicz
*/
public class OnlineIIRSinglechannelSampleFilterTest extends AbstractIIRSinglechannelSampleFilterTest {
private OnlineIIRSinglechannelSampleFilter engine;
@Override
protected OnlineIIRSinglechannelSampleFilter getEngine(MultichannelSampleSource source, FilterCoefficients coefficients) {
return new OnlineIIRSinglechannelSampleFilter(new ChannelSelectorSampleSource(source,0), coefficients);
}
/**
* Test method for {@link AbstractIIRSinglechannelSampleFilter#getUnfilteredSamplesCache(int)}.
*/
@Test
public void testGetUnfilteredSamplesCache() {
coefficients = new FilterCoefficients(new double[] {1.0,0.0,0.0,0.0}, new double[] {1.0,0.0,0.0,0.0});
engine = getEngine(source, coefficients);
//testing empty then full
float[] samples = new float[TEST_SAMPLE_COUNT];
for (int i = 0; i < TEST_SAMPLE_COUNT; i++) {
samples[i] = (float) Math.random();
}
for (int i = 0; i < TEST_SAMPLE_COUNT; i++)
source.addSamples(new float[] {samples[i]});
double[] uCache = engine.getUnfilteredSamplesCache(source.getSampleCount(0));
//System.out.println("uCache.length="+uCache.length);
for (int i = 0; i < TEST_SAMPLE_COUNT; i++) {
if (samples.length - i - 1 >= 0)
assertEquals(uCache[uCache.length - i - 1], samples[samples.length - i - 1], 0.000001);
else
assertEquals(uCache[uCache.length - i], 0.0, 0.00000001);
}
//adding 2 samples
float[] newSamples = new float[] {(float) Math.random(), (float) Math.random()};
source.addSamples(new float[] {newSamples[0]});
source.addSamples(new float[] {newSamples[1]});
uCache = engine.getUnfilteredSamplesCache(2);
assertEquals(uCache[0], samples[samples.length-3], 0.00001);
assertEquals(uCache[1], samples[samples.length-2], 0.00001);
assertEquals(uCache[2], samples[samples.length-1], 0.00001);
assertEquals(uCache[3], newSamples[0], 0.00001);
assertEquals(uCache[4], newSamples[1], 0.00001);
//one more sample added
float[] newNewSamples = new float[] {(float) Math.random()};
source.addSamples(newNewSamples);
uCache = engine.getUnfilteredSamplesCache(1);
assertEquals(uCache[0], samples[samples.length - 1], 0.00001);
assertEquals(uCache[1], newSamples[0], 0.00001);
assertEquals(uCache[2], newSamples[1], 0.00001);
assertEquals(uCache[3], newNewSamples[0], 0.00001);
}
/**
* Test method for {@link AbstractIIRSinglechannelSampleFilter#getFilteredSamplesCache(int)}.
*/
@Test
public void testGetFilteredSamplesCache() {
coefficients = new FilterCoefficients(new double[] {1.0, 0.0, 0.0, 0.0},
new double[] {1.0, 0.0, 0.0, 0.0});
engine = getEngine(source, coefficients);
double[] fCache = engine.getFilteredSamplesCache(source.getSampleCount(0));
assertEquals(fCache.length, source.getSampleCount(0) + 3, 0.00001);
for (int i = 0; i < fCache.length; i++)
assertEquals(fCache[i], 0.0, 0.000001);
//adding one sample
double[] samples = new double[] {Math.random()};
engine.filtered.addSamples(samples);
double x[] = new double[engine.filtered.getSampleCount()];
engine.filtered.getSamples(x, 0, engine.filtered.getSampleCount(), 0);
fCache = engine.getFilteredSamplesCache(2);
assertEquals(fCache.length, 3 + 2, 0.000001);
assertEquals(fCache[0], 0.0, 0.000001);
assertEquals(fCache[1], 0.0, 0.000001);
assertEquals(fCache[2], samples[0], 0.000001);
assertEquals(fCache[3], 0.0, 0.000001);
assertEquals(fCache[4], 0.0, 0.000001);
//added 2 filtered
double[] newFilteredSamples = new double[2];
newFilteredSamples[0] = Math.random();
newFilteredSamples[1] = Math.random();
engine.filtered.addSamples(new double[] {newFilteredSamples[0]});
engine.filtered.addSamples(new double[] {newFilteredSamples[1]});
fCache = engine.getFilteredSamplesCache(1);
assertEquals(fCache.length, 3 + 1, 0.000001);
assertEquals(fCache[0], samples[0], 0.000001);
assertEquals(fCache[1], newFilteredSamples[0],0.000001);
assertEquals(fCache[2], newFilteredSamples[1],0.000001);
assertEquals(fCache[3], 0.0, 0.000001);
//added 1 filtered
double[] new3 = new double[1];
new3[0] = Math.random();
engine.filtered.addSamples(new3);
fCache = engine.getFilteredSamplesCache(3);
assertEquals(fCache.length, 3 + 3, 0.000001);
assertEquals(fCache[0], newFilteredSamples[0], 0.000001);
assertEquals(fCache[1], newFilteredSamples[1], 0.000001);
assertEquals(fCache[2], new3[0], 0.000001);
assertEquals(fCache[3], 0.0, 0.000001);
assertEquals(fCache[4], 0.0, 0.000001);
assertEquals(fCache[5], 0.0, 0.000001);
}
/**
* Test method for {@link AbstractIIRSinglechannelSampleFilter#calculateNewFilteredSamples(double[], double[], int)}.
*/
@Test
public void testCalculateNewFilteredSamples() {
coefficients = new FilterCoefficients(new double[] {1.0, 0.0, 0.0},
new double[] {1.0, 0.0, 0.0});
engine = getEngine(source, coefficients);
//adding whole at once
double[] samples = new double[TEST_SAMPLE_COUNT];
for (int i = 0; i < TEST_SAMPLE_COUNT; i++) {
samples[i] = Math.random();
source.addSamples(new float[] {(float) samples[i]});
}
double[] uCache = engine.getUnfilteredSamplesCache(source.getSampleCount(0));
double[] fCache = engine.getFilteredSamplesCache(source.getSampleCount(0));
double[] newFiltered = engine.calculateNewFilteredSamples(uCache, fCache, TEST_SAMPLE_COUNT);
for (int i = 0; i < newFiltered.length; i++)
assertEquals(newFiltered[i], samples[i], 0.0001);
//two more samples
double[] newSamples1 = new double[] {Math.random(), Math.random()};
source.addSamples(new float[] {(float) newSamples1[0]});
source.addSamples(new float[] {(float) newSamples1[1]});
uCache = engine.getUnfilteredSamplesCache(2);
fCache = engine.getFilteredSamplesCache(2);
newFiltered = engine.calculateNewFilteredSamples(uCache, fCache, 2);
assertEquals(newFiltered[0], newSamples1[0], 0.00001);
assertEquals(newFiltered[1], newSamples1[1], 0.000001);
}
/**
* Test method for {@link AbstractIIRSinglechannelSampleFilter#filter(double[], double[], double[])}.
*/
@Test
public void testFilterUsingCache() {
//test1
double[] bCoefficients = new double[] {0.6, 0.22};
double[] aCoefficients = new double[] {1, 0.3, 0.4};
double[] input = new double[] {1, 2, 3, 4, 5, 6, 7, 8};
double[] filtered = OnlineIIRSinglechannelSampleFilter.filterUsingCache(bCoefficients, aCoefficients, input);
assertArrayEquals(new double[] {0.6, 1.24, 1.628, 2.0756, 2.60612, 3.087924,
3.5511748, 4.03947796
}, filtered, 0.0001);
//test 2
bCoefficients = new double[]
{0.00041655, 0.00124964, 0.00124964, 0.00041655};
aCoefficients = new double[]
{1. , -2.6861574 , 2.41965511, -0.73016535};
double[] expected = new double[] {
-3.51122604e-04, -2.38131593e-03, -8.12411562e-03,
-1.92823059e-02, -3.67895555e-02, -6.09388992e-02,
-9.14851744e-02, -1.27775036e-01, -1.68903987e-01,
-2.13765619e-01, -2.61092007e-01, -3.09599360e-01,
-3.58202192e-01, -4.06031337e-01, -4.52285424e-01,
-4.96254027e-01, -5.37334264e-01, -5.74939493e-01,
-6.08509899e-01, -6.37580060e-01, -6.61807439e-01,
-6.80963281e-01, -6.94950331e-01, -7.03822359e-01,
-7.07710463e-01, -7.06751512e-01, -7.01072375e-01,
-6.90813313e-01, -6.76248964e-01, -6.57854003e-01,
-6.36167663e-01, -6.11682852e-01, -5.84847851e-01,
-5.55987815e-01, -5.25304624e-01
};
filtered = OnlineIIRSinglechannelSampleFilter.filterUsingCache(bCoefficients, aCoefficients, TestingSignals.SHORT_SIGNAL);
assertArrayEquals(expected, filtered, 1e-4);
}
/**
* Test method for {@link AbstractIIRSinglechannelSampleFilter#filter(double[], double[], double[], double[]) }
*/
@Test
public void testFilterWithInitialState() {
double[] expectedFilteringResult = new double[] {
-0.95002814, -0.94980805, -0.94927655, -0.94834121, -0.94690188,
-0.94483862, -0.94198763, -0.93815852, -0.93319191, -0.92692217,
-0.9191435 , -0.90969293, -0.89861251, -0.88612545, -0.87245471,
-0.85782158, -0.84244496, -0.82643911, -0.8098189 , -0.79256666,
-0.77466379, -0.75608793, -0.73683938, -0.71697098, -0.6965261 ,
-0.67547935, -0.6537334 , -0.63115479, -0.60770691, -0.58352705,
-0.5588013 , -0.53366318, -0.50820369, -0.48239998, -0.45612131
};
double[] bCoefficients = new double[]
{0.00041655, 0.00124964, 0.00124964, 0.00041655};
double[] aCoefficients = new double[]
{1. , -2.6861574 , 2.41965511, -0.73016535};
double[] initialState = new double[] {
-0.9496770216294348, 1.603555227411396, -0.6941059685801035
};
double[] actualFilteringResult = AbstractIIRSinglechannelSampleFilter.filter(bCoefficients, aCoefficients, TestingSignals.SHORT_SIGNAL, initialState);
assertArrayEquals(expectedFilteringResult, actualFilteringResult, 1e-4);
}
}