package edu.hawaii.jmotif.sax;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import java.util.Iterator;
import org.junit.Test;
import edu.hawaii.jmotif.sax.alphabet.Alphabet;
import edu.hawaii.jmotif.sax.alphabet.NormalAlphabet;
import edu.hawaii.jmotif.sax.datastructures.SAXFrequencyData;
import edu.hawaii.jmotif.sax.datastructures.SAXFrequencyEntry;
import edu.hawaii.jmotif.timeseries.TSException;
import edu.hawaii.jmotif.timeseries.TSUtils;
import edu.hawaii.jmotif.timeseries.Timeseries;
import java.util.Set;
import java.util.TreeSet;
/**
* Test SAX factory methods.
*
* @author Pavel Senin
*
*/
public class TestSAXFactory {
private static final String ts1File = "RCode/data/timeseries01.csv";
private static final String ts2File = "RCode/data/timeseries02.csv";
private static final String ts1StrRep10 = "bcjkiheebb";
private static final String ts2StrRep10 = "bcefgijkdb";
private static final String ts1StrRep14 = "bcdijjhgfeecbb";
private static final String ts2StrRep14 = "bbdeeffhijjfbb";
private static final String ts1StrRep7 = "bcggfddba";
private static final String ts2StrRep7 = "accdefgda";
private static final int length = 15;
private static final int strLength = 10;
private static final Alphabet normalA = new NormalAlphabet();
private static final double delta = 0.000001;
/**
* Test the SAX conversion.
*
* @throws Exception if error occurs.
*/
@Test
public void testTs2string() throws Exception {
Timeseries ts1 = TSUtils.readTS(ts1File, length);
Timeseries ts2 = TSUtils.readTS(ts2File, length);
// series #1 based test
String ts1sax = SAXFactory.ts2string(ts1, 10, normalA, 11);
assertEquals("testing SAX", strLength, ts1sax.length());
assertTrue("testing SAX", ts1StrRep10.equalsIgnoreCase(ts1sax));
ts1sax = SAXFactory.ts2string(ts1, 14, normalA, 10);
assertEquals("testing SAX", 14, ts1sax.length());
assertTrue("testing SAX", ts1StrRep14.equalsIgnoreCase(ts1sax));
ts1sax = SAXFactory.ts2string(ts1, 9, normalA, 7);
assertEquals("testing SAX", 9, ts1sax.length());
assertTrue("testing SAX", ts1StrRep7.equalsIgnoreCase(ts1sax));
// series #2 goes here
String ts2sax = SAXFactory.ts2string(ts2, 10, normalA, 11);
assertEquals("testing SAX", strLength, ts2sax.length());
assertTrue("testing SAX", ts2StrRep10.equalsIgnoreCase(ts2sax));
ts2sax = SAXFactory.ts2string(ts2, 14, normalA, 10);
assertEquals("testing SAX", 14, ts2sax.length());
assertTrue("testing SAX", ts2StrRep14.equalsIgnoreCase(ts2sax));
ts2sax = SAXFactory.ts2string(ts2, 9, normalA, 7);
assertEquals("testing SAX", 9, ts2sax.length());
assertTrue("testing SAX", ts2StrRep7.equalsIgnoreCase(ts2sax));
}
/**
* Test the distance function.
*
* @throws Exception if error occur.
*/
@Test
public void testTs2sax() throws Exception {
Timeseries ts1 = TSUtils.readTS(ts1File, length);
Timeseries ts2 = TSUtils.readTS(ts2File, length);
String ts2str_0 = SAXFactory.ts2string(ts2.subsection(0, 4), 5, normalA, 10);
String ts2str_3 = SAXFactory.ts2string(ts2.subsection(3, 7), 5, normalA, 10);
String ts2str_7 = SAXFactory.ts2string(ts2.subsection(7, 11), 5, normalA, 10);
SAXFrequencyData ts2SAX = SAXFactory.ts2saxZNorm(TSUtils.zNormalize(ts2), 5, 5, normalA, 10);
assertEquals("Testing ts2saxOptimized", (Integer) (ts2.size() - 5 + 1), ts2SAX.size());
assertTrue("Testing ts2sax", ts2SAX.contains(ts2str_0));
assertTrue("Testing ts2sax", ts2SAX.contains(ts2str_3));
assertTrue("Testing ts2sax", ts2SAX.contains(ts2str_7));
assertSame("Testing ts2sax", ts2SAX.get(ts2str_0).getEntries().get(0), 0);
assertSame("Testing ts2sax", ts2SAX.get(ts2str_3).getEntries().get(0), 3);
assertSame("Testing ts2sax", ts2SAX.get(ts2str_7).getEntries().get(0), 7);
}
/**
* Test the distance function.
*
* @throws TSException if error occurs.
*/
@Test
public void testStringDistance() throws TSException {
double testDelta = 0.010000;
assertEquals("testing SAX distance", 0, SAXFactory.strDistance(new char[] { 'a' },
new char[] { 'b' }));
assertEquals("testing SAX distance", 2, SAXFactory.strDistance(new char[] { 'a', 'a', 'a' },
new char[] { 'b', 'c', 'b' }));
Alphabet a = new NormalAlphabet();
assertEquals("testing SAX distance", 0.86D, SAXFactory.saxMinDist(new char[] { 'a', 'a', 'a' },
new char[] { 'b', 'c', 'b' }, a.getDistanceMatrix(3)), testDelta);
assertEquals("testing SAX distance", 0.0D, SAXFactory.saxMinDist(new char[] { 'a', 'a', 'a' },
new char[] { 'b', 'b', 'b' }, a.getDistanceMatrix(3)), testDelta);
}
/**
* Test the SAX conversion when NaN's presented in the timeseries.
*
* @throws Exception if error occurs.
*/
@Test
public void testTs2stringWithNAN() throws Exception {
// read the timeseries first
Timeseries ts1 = TSUtils.readTS(ts1File, length);
Timeseries ts2 = TSUtils.readTS(ts2File, length);
// series #1 based test
String ts1sax = SAXFactory.ts2string(ts1, 10, normalA, 11);
assertEquals("testing SAX", strLength, ts1sax.length());
assertTrue("testing SAX", ts1StrRep10.equalsIgnoreCase(ts1sax));
Timeseries ts1WithNaN = new Timeseries(ts1.values(), ts1.tstamps(), ts1.values()[2]);
String tsWithNaN1sax = String.valueOf(TSUtils.ts2StringWithNaNByCuts(ts1WithNaN, normalA
.getCuts(11)));
assertSame("Checking Z conversion", tsWithNaN1sax.charAt(2), '_');
SAXFrequencyData tsWithNaN = SAXFactory.ts2saxNoZnormByCuts(ts1WithNaN, 14, 14, normalA
.getCuts(11));
SAXFrequencyEntry sfe = tsWithNaN.getSortedFrequencies().get(0);
assertSame("Checking Z conversion", sfe.getSubstring().charAt(1), '_');
}
/**
* Test the SAX conversion when NaN's presented in the timeseries.
*
* @throws Exception if error occurs.
*/
@Test
public void testTs2saxZnormByCuts() throws Exception {
//
// get series
Timeseries timeSeries01 = TSUtils.readTS(ts1File, length);
Timeseries timeSeries02 = TSUtils.readTS(ts2File, length);
//
// convert to sax with 2 letters alphabet and internal normalization
double[] cut = { 0.0D };
SAXFrequencyData sax = SAXFactory.ts2saxZnormByCuts(timeSeries01, 14, 10, cut);
Iterator<SAXFrequencyEntry> i = sax.iterator();
SAXFrequencyEntry entry0 = i.next();
assertTrue("Testing SAX routines", entry0.getSubstring().equalsIgnoreCase("aabbbbaaaa"));
sax = SAXFactory.ts2saxZnormByCuts(timeSeries01, 2, 2, cut);
i = sax.iterator();
entry0 = i.next();
SAXFrequencyEntry entry1 = i.next();
assertFalse("Testing SAX routines", entry0.getSubstring().equalsIgnoreCase(
entry1.getSubstring()));
// test double[] version here
double[] data = new double[timeSeries01.size()];
for (int k = 0; k < data.length; k++) {
data[k] = timeSeries01.elementAt(k).value();
}
sax = SAXFactory.ts2saxZnormByCuts(data, 14, 10, cut);
i = sax.iterator();
entry0 = i.next();
assertTrue("Testing SAX routines", entry0.getSubstring().equalsIgnoreCase("aabbbbaaaa"));
}
@Test
public void testTs2saxNoZnormByCuts() throws Exception {
//
// get series
Timeseries ts1 = TSUtils.readTS(ts1File, length);
Timeseries ts2 = TSUtils.readTS(ts2File, length);
//
// convert to sax with 2 letters alphabet and internal normalization
double[] cut = { 0.0D };
SAXFrequencyData sax = SAXFactory.ts2saxNoZnormByCuts(ts1, 14, 10, cut);
Iterator<SAXFrequencyEntry> i = sax.iterator();
SAXFrequencyEntry entry0 = i.next();
String expected = "bbbbbbbbbb";
String actual = entry0.getSubstring().toLowerCase();
assertEquals("Testing SAX routines", expected, actual);
}
/**
* Test the SAX conversion when NaN's presented in the timeseries.
*
* @throws Exception if error occurs.
*/
@Test
public void testTs2saxNoZnormByCutsWithNegativeNumbers() throws Exception {
//
// get series
Timeseries ts1 = TSUtils.readTS(ts1File, length);
Timeseries ts2 = TSUtils.readTS(ts2File, length);
//
// convert to sax with 2 letters alphabet and internal normalization
double[] cut = { 0.0D };
//
// now add two negatives
ts1.elementAt(5).setValue(-5.0D);
ts1.elementAt(4).setValue(-5.0D);
SAXFrequencyData sax = SAXFactory.ts2saxNoZnormByCuts(ts1, 14, 10, cut);
Set<String> expected = new TreeSet();
expected.add("bbabbbbbbb");
expected.add("bbbabbbbbb");
Set<String> actual = new TreeSet();
Iterator<SAXFrequencyEntry> i = sax.iterator();
while (i.hasNext()) {
SAXFrequencyEntry e = i.next();
actual.add(e.getSubstring().toLowerCase());
}
assertEquals("Testing SAX routines", expected, actual);
//
//
//sax = SAXFactory.ts2saxNoZnormByCuts(ts1, 2, 2, cut);
//i = sax.iterator();
//entry0 = i.next();
//SAXFrequencyEntry entry1 = i.next();
//System.out.println("entry0.getSubstring().equalsIgnoreCase(entry1.getSubstring()): " + entry0.getSubstring().equalsIgnoreCase(entry1.getSubstring()));
//assertFalse("Testing SAX routines", entry0.getSubstring().equalsIgnoreCase(entry1.getSubstring()));
}
/**
* Test the SAX conversion when NaN's presented in the timeseries.
*
* @throws Exception if error occurs.
*/
@Test
public void testTs2saxNoZnormByCuts_2_by_2() throws Exception {
//
// get series
Timeseries ts1 = TSUtils.readTS(ts1File, length);
Timeseries ts2 = TSUtils.readTS(ts2File, length);
//
// convert to sax with 2 letters alphabet and internal normalization
double[] cut = { 0.0D };
//
// now add two negatives
ts1.elementAt(5).setValue(-5.0D);
ts1.elementAt(4).setValue(-5.0D);
SAXFrequencyData sax = SAXFactory.ts2saxNoZnormByCuts(ts1, 2, 2, cut);
Set<String> expected = new TreeSet();
expected.add("aa");
expected.add("ab");
expected.add("ba");
expected.add("bb");
Set<String> actual = new TreeSet();
Iterator<SAXFrequencyEntry> i = sax.iterator();
while (i.hasNext()) {
SAXFrequencyEntry e = i.next();
actual.add(e.getSubstring().toLowerCase());
}
assertEquals("Testing SAX routines", expected, actual);
}
/**
* Test the distance function (between strings).
*/
@Test
public void testStrDistance() {
assertEquals("Testing StrDistance", 1, SAXFactory.strDistance('a', 'b'));
assertEquals("Testing StrDistance", 5, SAXFactory.strDistance('a', 'f'));
}
}