package picard.illumina.parser;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
import picard.PicardException;
import java.io.File;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.List;
public class FilterParserTest {
private static final File TestDataDir = new File("testdata/picard/illumina/parserTests");
private static final File BaseCallsDir = new File(TestDataDir, "filterParser");
private static final boolean F = false;
private static final boolean T = true;
public static final Boolean[] s_1_0001_filter = {F, F, T, F, T, T, F, F, T, F, T, T, F, T, T};
public static final Boolean[] s_1_0002_filter = {F, F, F, F, F, T, T, F, F, F, F, T, F, F, F, T, T, T, T, T};
public static final Boolean[] s_1_0003_filter = {T, F, F, F, T, T, F, F};
public static final Boolean[] s_1_0004_filter = {T, F, F, F, F, T, F, F, F, F, T, F, F, F, F, T, T, F, F, T,
T, F, T, F, T, T, F, F, T, T, F, T, T, T, T, F, T, T, T, T,
F, T, F, F, F, T, F, T, F, T, T, F, F, T, T, T, F, F, T, T};
public static final Boolean[] tileToValue(int tile) {
switch (tile) {
case 1:
return s_1_0001_filter;
case 2:
return s_1_0002_filter;
case 3:
return s_1_0003_filter;
case 4:
return s_1_0004_filter;
}
throw new RuntimeException("You shouldn't reach this statement!");
}
public static final Boolean[] allTilesToValues(Integer[] tiles) {
Boolean[][] values = new Boolean[tiles.length][];
for (int i = 0; i < tiles.length; i++) {
values[i] = tileToValue(tiles[i]);
}
return arrayFlatten(values);
}
public static final List<Integer> arrayToList(final Integer[] array) {
final List<Integer> list = new ArrayList<Integer>();
for (int item : array) {
list.add(item);
}
return list;
}
public static final <T> T[] arrayFlatten(final T[][] arrays) {
int total = 0;
for (T[] arr : arrays) {
total += arr.length;
}
int resultIndex = 0;
final T[] result = (T[]) Array.newInstance(arrays[0][0].getClass(), total);
for (int i = 0; i < arrays.length; i++) {
System.arraycopy(arrays[i], 0, result, resultIndex, arrays[i].length);
resultIndex += arrays[i].length;
}
return result;
}
@DataProvider(name = "passingTiles")
public Object[][] passingTiles() {
return new Object[][]{
{new Integer[]{1}},
{new Integer[]{2}},
{new Integer[]{4}},
{new Integer[]{1, 4}},
{new Integer[]{2, 3}},
{new Integer[]{1, 2, 3, 4}}
};
}
@Test(dataProvider = "passingTiles")
public void passingParserTest(Integer[] tiles) {
final IlluminaFileUtil fUtil = new IlluminaFileUtil(BaseCallsDir, 1);
final Boolean[] values = allTilesToValues(tiles);
final List<Integer> tileList = arrayToList(tiles);
final FilterParser fp = new FilterParser(((PerTileFileUtil) fUtil.getUtil(IlluminaFileUtil.SupportedIlluminaFormat.Filter)).getFiles(tileList));
fp.verifyData(tileList, null); //filter parser doesn't care about cycle
for (final boolean expectedValue : values) {
Assert.assertTrue(fp.hasNext());
Assert.assertEquals(fp.next().isPf(), expectedValue);
}
Assert.assertFalse(fp.hasNext());
//seek back to the beginning and do it again!
fp.seekToTile(tiles[0]);
for (final boolean expectedValue : values) {
Assert.assertTrue(fp.hasNext());
Assert.assertEquals(fp.next().isPf(), expectedValue);
}
Assert.assertFalse(fp.hasNext());
fp.close();
}
@DataProvider(name = "seekToTile")
public Object[][] seekToTile() {
return new Object[][]{
//seek after how many, tiles to load, expected values
{0, 2, new Integer[]{2}, new Boolean[][]{s_1_0002_filter}},
{4, 4, new Integer[]{1, 4}, new Boolean[][]{new Boolean[]{F, F, T, F}, s_1_0004_filter}},
{0, 3, new Integer[]{2, 3}, new Boolean[][]{s_1_0003_filter}},
{15, 3, new Integer[]{1, 2, 3, 4}, new Boolean[][]{s_1_0001_filter, s_1_0003_filter, s_1_0004_filter}}
};
}
@Test(dataProvider = "seekToTile")
public void passingSeekingParserTest(int skipBefore, int tileToSkipTo, Integer[] tiles, Boolean[][] expectedValues) {
final IlluminaFileUtil fUtil = new IlluminaFileUtil(BaseCallsDir, 1);
final Boolean[] values = arrayFlatten(expectedValues);
final List<Integer> tileList = arrayToList(tiles);
final FilterParser fp = new FilterParser(((PerTileFileUtil) fUtil.getUtil(IlluminaFileUtil.SupportedIlluminaFormat.Filter)).getFiles(tileList));
int read = 0;
for (final boolean expectedValue : values) {
if (read == skipBefore) {
fp.seekToTile(tileToSkipTo);
}
Assert.assertTrue(fp.hasNext());
Assert.assertEquals(fp.next().isPf(), expectedValue, " Failed on read: " + read);
++read;
}
Assert.assertFalse(fp.hasNext());
fp.close();
}
@DataProvider(name = "failingVerifyTiles")
public Object[][] failingVerifyTiles() {
return new Object[][]{
{new Integer[]{1}, new Integer[]{2}},
{new Integer[]{2}, new Integer[]{1}},
{new Integer[]{4}, new Integer[]{5}},
{new Integer[]{1, 4}, new Integer[]{1, 3, 4}},
{new Integer[]{2, 3}, new Integer[]{2, 3, 4}},
{new Integer[]{1, 2, 3, 4}, new Integer[]{1, 2, 3, 4, 5}},
{new Integer[]{2, 3, 4}, new Integer[]{1, 2, 3, 4}}
};
}
@Test(dataProvider = "failingVerifyTiles", expectedExceptions = PicardException.class)
public void verifyDataTest(final Integer[] initTiles, final Integer[] verifyTiles) {
final IlluminaFileUtil fUtil = new IlluminaFileUtil(BaseCallsDir, 1);
final List<Integer> initTileList = arrayToList(initTiles);
final List<Integer> verifyTileList = arrayToList(verifyTiles);
final FilterParser fp = new FilterParser(((PerTileFileUtil) fUtil.getUtil(IlluminaFileUtil.SupportedIlluminaFormat.Filter)).getFiles(initTileList));
fp.verifyData(verifyTileList, null); //filter parser doesn't care about cycle values
fp.close();
}
}