package edu.hawaii.jmotif.sax; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; import org.junit.Before; import org.junit.Test; import weka.core.Attribute; import weka.core.Instances; import weka.core.converters.ConverterUtils.DataSource; import edu.hawaii.jmotif.sax.alphabet.Alphabet; import edu.hawaii.jmotif.sax.alphabet.BuildTelemetryAlphabet; import edu.hawaii.jmotif.sax.alphabet.NormalAlphabet; import edu.hawaii.jmotif.sax.alphabet.UniversalTelemetryAlphabet; import edu.hawaii.jmotif.timeseries.TPoint; import edu.hawaii.jmotif.timeseries.TSException; import edu.hawaii.jmotif.timeseries.TSUtils; import edu.hawaii.jmotif.timeseries.Timeseries; /** * Test the TSUtils. * * @author Pavel Senin. * * * * */ public class TestTSUtils { private static final String ts1File = "RCode/data/timeseries01.csv"; private static final String ts2File = "RCode/data/timeseries02.csv"; private static final String ts1NormFile = "RCode/data/timeseries01.norm.csv"; private static final String ts2NormFile = "RCode/data/timeseries02.norm.csv"; private static final String ts1PAAFile = "RCode/data/timeseries01.PAA10.csv"; private static final String ts2PAAFile = "RCode/data/timeseries02.PAA10.csv"; private static final String attribute = "value0"; private static final int length = 15; private static final int PAAlength = 10; private static final double delta = 0.000001; private static final double ts1Max = 9.2; private static final double ts1Min = 1.34; private static final double ts2Max = 8.83; private static final double ts2Min = 0.5; private static final Alphabet normalA = new NormalAlphabet(); private static final Alphabet buildA = new BuildTelemetryAlphabet(); private static final Alphabet universalA = new UniversalTelemetryAlphabet(); private static final double[] tsWithNaNs = { 1.0, 4.0, 7.0, 10.0, 2.0, 5.0, 8.0, 11.0, 3.0, 6.0, 9.0, 12 }; Timeseries ts1, ts2, ts1Norm, ts2Norm, ts1PAA10, ts2PAA10; /** * Test set-up. * * @throws Exception if error occurs. */ @Before public void setUp() throws Exception { ts1 = TSUtils.readTS(ts1File, length); ts2 = TSUtils.readTS(ts2File, length); } /** * Test the extremum calculations. */ @Test public void testExtremum() { assertEquals("max", ts1Max, TSUtils.max(ts1), delta); assertEquals("max", ts2Max, TSUtils.max(ts2), delta); assertEquals("min", ts1Min, TSUtils.min(ts1), delta); assertEquals("min", ts2Min, TSUtils.min(ts2), delta); // // now set the value of the second element as NaN ts1.elementAt(1).setValue(Double.NaN); ts2.elementAt(2).setValue(Double.NaN); assertEquals("max", ts1Max, TSUtils.max(ts1), delta); assertEquals("max", ts2Max, TSUtils.max(ts2), delta); assertEquals("min", ts1Min, TSUtils.min(ts1), delta); assertEquals("min", ts2Min, TSUtils.min(ts2), delta); } /** * Test the mean calculation. */ @Test public void testMean() { assertEquals("mean", 4.606667, TSUtils.mean(ts1), delta); assertEquals("mean", 4.606667, TSUtils.mean(ts1.values()), delta); assertEquals("mean", 4.01, TSUtils.mean(ts2), delta); assertEquals("mean", 4.01, TSUtils.mean(ts2.values()), delta); // // now set the value of the second element as NaN ts1.elementAt(0).setValue(Double.NaN); ts2.elementAt(0).setValue(Double.NaN); assertEquals("mean", 4.791429, TSUtils.mean(ts1), delta); assertEquals("mean", 4.791429, TSUtils.mean(ts1.values()), delta); assertEquals("mean", 4.260714, TSUtils.mean(ts2), delta); assertEquals("mean", 4.260714, TSUtils.mean(ts2.values()), delta); } /** * Test the variance calculation. */ @Test public void testVar() { assertEquals("variance", 6.971267, TSUtils.var(ts1), delta); assertEquals("variance", 6.971267, TSUtils.var(ts1.values()), delta); assertEquals("variance", 7.409971, TSUtils.var(ts2), delta); assertEquals("variance", 7.409971, TSUtils.var(ts2.values()), delta); // // now set the value of the second element as NaN ts1.elementAt(0).setValue(Double.NaN); ts2.elementAt(0).setValue(Double.NaN); assertEquals("variance", 6.956075, TSUtils.var(ts1), delta); assertEquals("variance", 6.956075, TSUtils.var(ts1.values()), delta); assertEquals("variance", 6.964576, TSUtils.var(ts2), delta); assertEquals("variance", 6.964576, TSUtils.var(ts2.values()), delta); } /** * Test the standard deviation calculation. */ @Test public void testStdev() { assertEquals("stdev", 2.640316, TSUtils.stDev(ts1), delta); assertEquals("stdev", 2.640316, TSUtils.stDev(ts1.values()), delta); ts1.elementAt(0).setValue(Double.NaN); assertEquals("stdev", 2.637437, TSUtils.stDev(ts1), delta); assertEquals("stdev", 2.637437, TSUtils.stDev(ts1.values()), delta); assertEquals("stdev", 2.722126, TSUtils.stDev(ts2), delta); assertEquals("stdev", 2.722126, TSUtils.stDev(ts2.values()), delta); } /** * Test the normalize routine. * * @throws Exception if error occurs. */ @Test public void testNormalize() throws Exception { // read the normalized data ts1Norm = TSUtils.readTS(ts1NormFile, length); ts2Norm = TSUtils.readTS(ts2NormFile, length); // get the normal data through the code Timeseries ts1NormTest = TSUtils.zNormalize(ts1); double[] ts1NormDoubleTest = TSUtils.zNormalize(ts1.values()); Timeseries ts2NormTest = TSUtils.zNormalize(ts2); // get data for testing as arrays double[] ts1TrueValues = ts1Norm.values(); double[] ts1TestValues = ts1NormTest.values(); assertEquals("normalization", ts1TrueValues.length, ts1TestValues.length); for (int i = 0; i < ts1TrueValues.length; i++) { assertEquals("normalization", ts1TrueValues[i], ts1TestValues[i], delta); assertEquals("normalization", ts1TrueValues[i], ts1NormDoubleTest[i], delta); } double[] ts2Values = new double[ts2Norm.size()]; double[] ts2TestValues = new double[ts2NormTest.size()]; assertEquals("normalization", ts2Values.length, ts2TestValues.length); for (int i = 0; i < ts2Values.length; i++) { assertEquals("normalization", ts2Values[i], ts2TestValues[i], delta); } } /** * Test the normalize routine. * * @throws Exception if error occurs. */ @Test public void testNormalizeWithNaN1() throws Exception { // // test for single value within the timeseries. // length of the ts1 is 14, let's keep only value at the position 5 for (int i = 0; i < ts1.size(); i++) { if (4 == i) { continue; } ts1.elementAt(i).setValue(Double.NaN); } ts1Norm = TSUtils.zNormalize(ts1); assertEquals("Test normalize", 1.0, ts1Norm.elementAt(4).value(), 0.00001D); assertTrue("Test normalize", Double.isNaN(ts1Norm.elementAt(2).value())); assertTrue("Test normalize", Double.isNaN(ts1Norm.elementAt(6).value())); double[] ts1Norm1 = TSUtils.zNormalize(ts1.values()); assertEquals("Test normalize", 1.0, ts1Norm1[4], 0.00001D); assertTrue("Test normalize", Double.isNaN(ts1Norm1[2])); assertTrue("Test normalize", Double.isNaN(ts1Norm1[6])); } /** * Test the normalize routine. * * @throws Exception if error occurs. */ @Test public void testNormalizeWithNaN2() throws Exception { // // test for all NaN's // length of the ts1 is 14, let's keep only value at the position 5 for (int i = 0; i < ts1.size(); i++) { ts1.elementAt(i).setValue(Double.NaN); } ts1Norm = TSUtils.zNormalize(ts1); assertTrue("Test normalize", Double.isNaN(ts1Norm.elementAt(2).value())); assertTrue("Test normalize", Double.isNaN(ts1Norm.elementAt(6).value())); double[] ts1Norm1 = TSUtils.zNormalize(ts1.values()); assertTrue("Test normalize", Double.isNaN(ts1Norm1[2])); assertTrue("Test normalize", Double.isNaN(ts1Norm1[6])); } /** * Test the normalize routine. * * @throws Exception if error occurs. */ @Test public void testNormalizeWithNaN3() throws Exception { // // test for standard deviation = 0 // length of the ts1 is 14, let's keep only value at the position 5 for (int i = 0; i < ts1.size(); i++) { if (3 == i || 4 == i) { ts1.elementAt(i).setValue(3.0D); } else { ts1.elementAt(i).setValue(Double.NaN); } } ts1Norm = TSUtils.zNormalize(ts1); assertTrue("Test normalize", Double.isNaN(ts1Norm.elementAt(2).value())); assertEquals("Test normalize", 0.1D, ts1Norm.elementAt(3).value(), 0.00001D); assertEquals("Test normalize", 0.1D, ts1Norm.elementAt(4).value(), 0.00001D); assertTrue("Test normalize", Double.isNaN(ts1Norm.elementAt(5).value())); double[] ts1Norm1 = TSUtils.zNormalize(ts1.values()); assertTrue("Test normalize", Double.isNaN(ts1Norm1[2])); assertEquals("Test normalize", 0.1D, ts1Norm1[3], 0.00001D); assertEquals("Test normalize", 0.1D, ts1Norm1[4], 0.00001D); assertTrue("Test normalize", Double.isNaN(ts1Norm1[5])); } /** * Test the PAA routine. * * @throws Exception if error occurs. */ @Test public void testPAA() throws Exception { // read the normalized data ts1Norm = TSUtils.readTS(ts1NormFile, length); ts2Norm = TSUtils.readTS(ts2NormFile, length); // read the PAA data ts1PAA10 = TSUtils.readTS(ts1PAAFile, PAAlength); ts2PAA10 = TSUtils.readTS(ts2PAAFile, PAAlength); // get the normal data through the code Timeseries ts1PAATest = TSUtils.paa(ts1Norm, PAAlength); Timeseries ts2PAATest = TSUtils.paa(ts2Norm, PAAlength); // get data for testing as arrays double[] ts1TrueValues = ts1PAA10.values(); double[] ts1TestValues = ts1PAATest.values(); assertEquals("PAA", ts1TrueValues.length, ts1TestValues.length); for (int i = 0; i < ts1TrueValues.length; i++) { assertEquals("PAA", ts1TrueValues[i], ts1TestValues[i], delta); } // get data for testing as arrays double[] ts2TrueValues = ts2PAA10.values(); double[] ts2TestValues = ts2PAATest.values(); assertEquals("PAA", ts2TrueValues.length, ts2TestValues.length); for (int i = 0; i < ts2TrueValues.length; i++) { assertEquals("PAA", ts2TrueValues[i], ts2TestValues[i], delta); } } @Test public void testPAA2() throws Exception { double[] arr = { 2., 5., 10., 8., 4., 3., 2., 7., 12., 1. }; double[] paa1 = TSUtils.paa(arr, 7); double[] paa2 = TSUtils.optimizedPaa(arr, 7); assertEquals(paa1[0], paa2[0], 0.000000001); assertEquals(paa1[1], paa2[1], 0.000000001); } /** * Test the PAA routine timestamps. * * @throws Exception if error occurs. */ @Test public void testPAA1() throws Exception { // read the data Instances data = DataSource.read("data//ts_data//TEK16.arff"); // get the real-valued series Attribute dataAttribute = data.attribute(attribute); Timeseries ts = new Timeseries(); for (int i = 0; i < data.size(); i++) { ts.add(new TPoint(data.get(i).value(dataAttribute.index()), Integer.valueOf(i).longValue())); } Timeseries tsPAA = TSUtils.paa(ts, 5); long zero = 499L; long increment = 1000L; int i = 0; for (TPoint tp : tsPAA) { assertEquals(Long.valueOf(tp.tstamp()), Long.valueOf(zero + i * increment)); i = i + 1; } } /** * Test the normalize routine with NaN's. * * @throws Exception if error occurs. */ @Test public void testPAAWithNaNs() throws Exception { // get the time vector long[] time = new long[tsWithNaNs.length]; for (int i = 0; i < tsWithNaNs.length; i++) { time[i] = Long.valueOf(i); } // do PAA without NaN's Timeseries paa5 = TSUtils.paa(new Timeseries(tsWithNaNs, time), 5); Timeseries paa10 = TSUtils.paa(new Timeseries(tsWithNaNs, time), 10); // do PAA with NaN's tsWithNaNs[0] = Double.NaN; tsWithNaNs[1] = Double.NaN; Timeseries paa5nan = TSUtils.paa(new Timeseries(tsWithNaNs, time), 5); assertFalse("Test proper NaN's handling", Double.isNaN(paa5nan.elementAt(0).value())); assertEquals("Test proper NaN's handling", 7.0, paa5nan.elementAt(0).value(), 0.0000001); assertEquals("Test proper NaN's handling", paa5.elementAt(1).value(), paa5nan.elementAt(1) .value(), 0.0001); Timeseries paa10nan = TSUtils.paa(new Timeseries(tsWithNaNs, time), 10); assertTrue("Test proper NaN's handling", Double.isNaN(paa10nan.elementAt(0).value())); assertEquals("Test proper NaN's handling", paa10.elementAt(2).value(), paa10nan.elementAt(2) .value(), 0.0001); } /** * Test the SAX conversion. * * @throws TSException if error occurs. */ @Test public void testNum2Char() throws TSException { // private static final double[] case2 = { 0 }; assertEquals("test num2char", 'a', TSUtils.num2char(-0.5, normalA.getCuts(2))); assertEquals("test num2char", 'b', TSUtils.num2char(0.5, normalA.getCuts(2))); assertEquals("test num2char", 'b', TSUtils.num2char(0.0, normalA.getCuts(2))); double[] ts0 = { -0.5, 0.5, 0.0 }; long[] t = { 1L, 2L, 3L }; assertTrue("test num2char", "abb".equalsIgnoreCase(new String(TSUtils.ts2String(new Timeseries(ts0, t), normalA, 2)))); // private static final double[] case7 = { -1.07, -0.57, -0.18, 0.18, 0.57, 1.07 }; assertEquals("test num2char", 'd', TSUtils.num2char(-0.179, normalA.getCuts(7))); assertEquals("test num2char", 'd', TSUtils.num2char(-0.18, normalA.getCuts(7))); assertEquals("test num2char", 'c', TSUtils.num2char(-0.1801, normalA.getCuts(7))); double[] ts1 = { -0.179, -0.18, -0.1801 }; assertTrue("test num2char", "ddc".equalsIgnoreCase(new String(TSUtils.ts2String(new Timeseries(ts1, t), normalA, 7)))); // private static final double[] case2 = { -0.31629 }; assertEquals("test num2char", 'a', TSUtils.num2char(-0.32, buildA.getCuts(2))); assertEquals("test num2char", 'b', TSUtils.num2char(-0.315, buildA.getCuts(2))); assertEquals("test num2char", 'b', TSUtils.num2char(0.0, buildA.getCuts(2))); double[] ts2 = { -0.32, -0.315, 0.0 }; assertTrue("test num2char", "abb".equalsIgnoreCase(new String(TSUtils.ts2String(new Timeseries(ts2, t), buildA, 2)))); // private static final double[] case7 = { -0.682417, -0.48938550000000003, -0.3782755, // -0.189843, 0.0532246, 0.67971 }; assertEquals("test num2char", 'd', TSUtils.num2char(-0.375, buildA.getCuts(7))); assertEquals("test num2char", 'd', TSUtils.num2char(-0.1899, buildA.getCuts(7))); assertEquals("test num2char", 'c', TSUtils.num2char(-0.3787, buildA.getCuts(7))); double[] ts3 = { -0.375, -0.1899, -0.3787 }; assertTrue("test num2char", "ddc".equalsIgnoreCase(new String(TSUtils.ts2String(new Timeseries(ts3, t), buildA, 7)))); // private static final double[] case2 = { -0.098181 }; assertEquals("test num2char", 'a', TSUtils.num2char(-0.099, universalA.getCuts(2))); assertEquals("test num2char", 'b', TSUtils.num2char(-0.0980, universalA.getCuts(2))); assertEquals("test num2char", 'b', TSUtils.num2char(0.0, universalA.getCuts(2))); double[] ts4 = { -0.099, -0.098, 0.0 }; assertTrue("test num2char", "abb".equalsIgnoreCase(new String(TSUtils.ts2String(new Timeseries( ts4, t), universalA, 2)))); // private static final double[] case7 = { -0.795985, -0.443235, -0.165274, 0.0, 0.399261, // 0.77940 }; assertEquals("test num2char", 'd', TSUtils.num2char(-0.001, universalA.getCuts(7))); assertEquals("test num2char", 'd', TSUtils.num2char(-0.164, universalA.getCuts(7))); assertEquals("test num2char", 'c', TSUtils.num2char(-0.166, universalA.getCuts(7))); double[] ts5 = { -0.001, -0.164, -0.166 }; assertTrue("test num2char", "ddc".equalsIgnoreCase(new String(TSUtils.ts2String(new Timeseries( ts5, t), universalA, 7)))); double[] ts6 = { -0.001, Double.NEGATIVE_INFINITY, -0.166 }; assertTrue("test num2char", "d_c".equalsIgnoreCase(new String(TSUtils.ts2StringWithNaN( new Timeseries(ts6, t), universalA, 7)))); } /** * Test the SAX conversion. * * @throws Exception if error occurs. */ @Test public void testTS2Index() throws Exception { // read the PAA data ts1PAA10 = TSUtils.readTS(ts1PAAFile, PAAlength); int[] idx1 = TSUtils.ts2Index(ts1PAA10, normalA, 10); assertEquals("Testing ts2index", Integer.valueOf(idx1[1]), Integer.valueOf(2)); assertEquals("Testing ts2index", Integer.valueOf(idx1[3]), Integer.valueOf(9)); assertEquals("Testing ts2index", Integer.valueOf(idx1[7]), Integer.valueOf(4)); } /** * Test the data conversion. * * @throws TSException If error occurs. */ @Test public void testTypeConversion() throws TSException { double[][] valsAsMatix = ts2.valuesAsMatrix(); for (int i = 0; i < valsAsMatix.length; i++) { assertEquals(ts2.elementAt(i).value(), valsAsMatix[0][i], 0.01); } } }