package org.seqcode.data.readdb.unittests;
import java.util.*;
import java.io.*;
import org.junit.*;
import org.seqcode.data.readdb.FloatBP;
import org.seqcode.data.readdb.Header;
import org.seqcode.data.readdb.Hits;
import org.seqcode.data.readdb.IntBP;
import org.seqcode.data.readdb.SingleHits;
import static org.junit.Assert.*;
public class TestHits {
private IntBP hits, las;
private FloatBP weights;
private Header header;
private SingleHits hitsfile;
private static String prefix;
private static int chrom;
private static int MAXVALUE;
private static float MAXWEIGHT = 4f;
private static int NUMHITS = 100000;
public TestHits() throws IOException {
hits = new IntBP(NUMHITS);
weights = new FloatBP(NUMHITS);
las = new IntBP(NUMHITS);
int[] temp = new int[NUMHITS];
for (int i = 0; i < NUMHITS; i++) {
temp[i] = (int)Math.round(Math.random() * 4000);
}
Arrays.sort(temp);
for (int i = 0; i < NUMHITS; i++) {
hits.put(i, temp[i]);
}
MAXVALUE = hits.get(NUMHITS - 1);
for (int i = 0; i < hits.limit(); i++) {
weights.put(i,(float)(Math.random() * MAXWEIGHT));
las.put(i, Hits.makeLAS((short)(hits.get(i) % 500), hits.get(i) % 2 == 1,
(short)(hits.get(i) % 1000), hits.get(i) % 5 == 1));
}
SingleHits.writeSingleHits(hits, weights, las, prefix, chrom, false);
hitsfile = new SingleHits(prefix, chrom, false);
header = new Header(hitsfile.getPositionsBuffer().getib());
header.writeIndexFile(prefix + chrom + ".index");
header = Header.readIndexFile(prefix + chrom + ".index");
}
@Test public void testCount() {
assertTrue(hits.size() == header.getNumHits());
}
@Test public void testLAS() {
for (short s = 0; s < 1000; s += 10) {
int l = Hits.makeLAS(s, true);
assertTrue(Hits.getStrandOne(l));
assertEquals(Hits.getLengthOne(l), s);
l = Hits.makeLAS(s, false);
assertFalse(Hits.getStrandOne(l));
assertEquals(Hits.getLengthOne(l), s);
}
for (short s = 0; s < 1000; s += 10) {
for (short t = 0; t < 1000; t += 10) {
int l = Hits.makeLAS(s,true,t,true);
assertTrue(Hits.getStrandOne(l));
assertEquals(Hits.getLengthOne(l), s);
assertTrue(Hits.getStrandTwo(l));
assertEquals(Hits.getLengthTwo(l), t);
l = Hits.makeLAS(s,true,t,false);
assertTrue(Hits.getStrandOne(l));
assertEquals(Hits.getLengthOne(l), s);
assertFalse(Hits.getStrandTwo(l));
assertEquals(Hits.getLengthTwo(l), t);
l = Hits.makeLAS(s,false,t,true);
assertFalse(Hits.getStrandOne(l));
assertEquals(Hits.getLengthOne(l), s);
assertTrue(Hits.getStrandTwo(l));
assertEquals(Hits.getLengthTwo(l), t);
l = Hits.makeLAS(s,false,t,false);
assertFalse(Hits.getStrandOne(l));
assertEquals(Hits.getLengthOne(l), s);
assertFalse(Hits.getStrandTwo(l));
assertEquals(Hits.getLengthTwo(l), t);
}
}
}
@Test public void testGetAllHits (){
IntBP positions = hitsfile.getPositionsBuffer();
FloatBP w = hitsfile.getWeightsBuffer();
IntBP l = hitsfile.getLASBuffer();
boolean fail = false;
for (int i = 0; i < hits.size(); i++) {
if (positions.get(i) != hits.get(i)) {
System.err.println(String.format("At %d, %d != %d", i, positions.get(i), hits.get(i)));
fail = true;
}
if (Math.abs(w.get(i) - weights.get(i)) > .001) {
System.err.println(String.format("At %d, %.4f != %.4f",i,weights.get(i), w.get(i)));
fail = true;
}
if (l.get(i) != las.get(i)) {
System.err.println(String.format("At %d, las %d != %d", i, las.get(i), l.get(i)));
fail = true;
}
}
assertTrue(!fail);
}
@Test public void testCornerCases() {
int start = -100;
int end = -20;
int firstindex = header.getFirstIndex(start);
int lastindex = header.getLastIndex(end);
int p[] = hitsfile.getIndices(firstindex,lastindex,start,end);
assertTrue(p[0] >= p[1]);
start = MAXVALUE+10;
end = MAXVALUE+10;
firstindex = header.getFirstIndex(start);
lastindex = header.getLastIndex(end);
p = hitsfile.getIndices(firstindex,lastindex,start,end);
assertTrue(p[0] >= p[1]);
start = hits.get(1000);
firstindex = header.getFirstIndex(start);
lastindex = header.getLastIndex(end);
p = hitsfile.getIndices(firstindex,lastindex,start,end);
assertTrue(p[0] <= p[1]);
assertTrue(String.format("cornercase : %d,%d, %d,%d -> %d,%d",
start,end, firstindex, lastindex, p[0], p[1]), p[1] == header.getNumHits());
start = -10;
end = hits.get(1000);
firstindex = header.getFirstIndex(start);
lastindex = header.getLastIndex(end);
p = hitsfile.getIndices(firstindex,lastindex,start,end);
assertTrue(p[0] == 0);
}
@Test public void testGetIndices() {
boolean allok = true;
for (int q = 1; q < 5000; q++) {
int start = (int)Math.round(Math.random() * MAXVALUE);
int end = start + (int)Math.round(Math.random() * (MAXVALUE - start));
int firstindex = header.getFirstIndex(start);
int lastindex = header.getLastIndex(end);
int p[] = hitsfile.getIndices(firstindex,lastindex,start,end);
assertTrue(p[0] >= 0);
assertTrue(p[1] <= hits.size());
boolean ok = true;
if (p[0] == p[1]) {
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end) {
ok = false;
}
}
} else {
ok = (hits.get(p[0]) >= start && (p[0] == 0 || hits.get(p[0]-1) < start)) &&
(p[1] == hits.size() || hits.get(p[1]) > end && hits.get(p[1]-1) <= end);
}
if (!ok) {
System.err.println(String.format("Not OK : getIndices(%d,%d,%d,%d) -> %d,%d",
firstindex,lastindex,start,end,p[0],p[1]));
System.err.println(String.format(" %d,%d,%d .. %d, %d, %d",
(p[0] == 0 ? -10 : hits.get(p[0]-1)),hits.get(p[0]), hits.get(p[0]+1), hits.get(p[1]-1), (p[1] == hits.size() ? -10 : hits.get(p[1])), (p[1] == hits.size() - 1 ? -10 : hits.get(p[1]+1))));
}
allok = allok && ok;
}
assertTrue(allok);
}
@Test public void testCountRange() throws IOException {
for (int q = 0; q < 300; q++) {
int start = (int)Math.round(Math.random() * MAXVALUE);
int end = start + (int)(Math.round(Math.random() * MAXVALUE) % (MAXVALUE - start));
if (end < start) {
throw new RuntimeException("end < start");
}
int count = 0;
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end) {
count++;
}
}
int reported = hitsfile.getCountBetween(header.getFirstIndex(start),
header.getLastIndex(end),
start,end, null, null);
assertTrue(count == reported);
}
}
@Test public void testGetHits() throws IOException {
for (int q = 0; q < 300; q++) {
int start = (int)Math.round(Math.random() * MAXVALUE);
int end = start + (int)(Math.round(Math.random() * MAXVALUE) % (MAXVALUE - start));
if (end < start) {
throw new RuntimeException("end < start");
}
IntBP reported = hitsfile.getHitsBetween(header.getFirstIndex(start),
header.getLastIndex(end),
start,end, null, null);
FloatBP wreported = hitsfile.getWeightsBetween(header.getFirstIndex(start),
header.getLastIndex(end),
start,end, null, null);
int k = 0; int j = 0;
while (k < hits.size() && hits.get(k) < start) { k++;}
while (k < hits.size() && hits.get(k) <= end) {
if (hits.get(k) != reported.get(j)) {
System.err.println(String.format("Mismatch %d (%d) != %d (%d)",
hits.get(k), k, reported.get(j), j));
}
assertTrue(hits.get(k) == reported.get(j));
assertTrue(weights.get(k) == wreported.get(j));
k++;
j++;
}
}
}
@Test public void testHistogram() throws IOException {
for (int q = 0; q < 300; q++) {
int start = (int)Math.round(Math.random() * (MAXVALUE - 10));
int end = start + (int)(Math.round(Math.random() * MAXVALUE) % (MAXVALUE - start));
if (end < start) {
throw new RuntimeException("end < start");
}
int binsize = 10 + (int)Math.round(Math.random() * 40);
int[] histogram = hitsfile.histogram(header.getFirstIndex(start),
header.getLastIndex(end),
start,end,binsize,0,null,null,0);
int[] myhist = new int[(end - start) / binsize + 1];
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end) {
myhist[(hits.get(i) - start) / binsize]++;
}
}
assertTrue(myhist.length == histogram.length);
for (int i = 0; i < myhist.length; i++) {
assertTrue(myhist[i] == histogram[i]);
}
}
}
@Test public void testDeDupHistogram() throws IOException {
for (int q = 0; q < 300; q++) {
int start = (int)Math.round(Math.random() * (MAXVALUE - 10));
int end = start + (int)(Math.round(Math.random() * MAXVALUE) % (MAXVALUE - start));
if (end < start) {
throw new RuntimeException("end < start");
}
int binsize = 10 + (int)Math.round(Math.random() * 40);
int k = 0;
// while (hits.get(k) < binsize) {
// System.out.println("k=" + k + " val=" + hits.get(k));
// k++;
// }
int[] histogram = hitsfile.histogram(header.getFirstIndex(start),
header.getLastIndex(end),
start,end,binsize,1,null,null,0);
int[] myhist = new int[(end - start) / binsize + 1];
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end) {
if (i == 0 || hits.get(i-1) != hits.get(i)) {
myhist[(hits.get(i) - start) / binsize]++;
}
}
}
assertTrue(myhist.length == histogram.length);
for (int i = 0; i < myhist.length; i++) {
if (myhist[i] != histogram[i]) {
System.err.println(String.format("At dup1 %d, %d != %d",i,myhist[i],histogram[i]));
}
assertTrue(myhist[i] == histogram[i]);
}
histogram = hitsfile.histogram(header.getFirstIndex(start),
header.getLastIndex(end),
start,end,binsize,2,null,null,0);
myhist = new int[(end - start) / binsize + 1];
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end) {
if (i < 2 || (hits.get(i-1) != hits.get(i) ||
hits.get(i-2) != hits.get(i))) {
myhist[(hits.get(i) - start) / binsize]++;
}
}
}
assertTrue(myhist.length == histogram.length);
for (int i = 0; i < myhist.length; i++) {
if (myhist[i] != histogram[i]) {
System.err.println(String.format("At dup2 %d, %d != %d",i,myhist[i],histogram[i]));
}
assertTrue(myhist[i] == histogram[i]);
}
}
}
@Test public void testMinWeightHistogram() throws IOException {
for (int q = 0; q < 300; q++) {
int start = (int)Math.round(Math.random() * MAXVALUE);
int end = start + (int)(Math.round(Math.random() * MAXVALUE) % (MAXVALUE - start));
if (end < start) {
throw new RuntimeException("end < start");
}
int binsize = 10 + (int)Math.round(Math.random() * 40);
float weight = (float)Math.random() * MAXWEIGHT;
int[] histogram = hitsfile.histogram(header.getFirstIndex(start),
header.getLastIndex(end),
start,end,binsize,0,weight,null,0);
int[] myhist = new int[(end - start) / binsize + 1];
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end && weights.get(i) >= weight) {
myhist[(hits.get(i) - start) / binsize]++;
}
}
assertTrue(myhist.length == histogram.length);
for (int i = 0; i < myhist.length; i++) {
assertTrue(Math.abs(myhist[i] - histogram[i]) < .001);
}
}
}
@Test public void testWeightHistogram() throws IOException {
for (int q = 0; q < 300; q++) {
int start = (int)Math.round(Math.random() * MAXVALUE);
int end = start + (int)(Math.round(Math.random() * MAXVALUE) % (MAXVALUE - start));
if (end < start) {
throw new RuntimeException("end < start");
}
int binsize = 10 + (int)Math.round(Math.random() * 40);
float[] histogram = hitsfile.weightHistogram(header.getFirstIndex(start),
header.getLastIndex(end),
start,end,binsize,0,null,null,0);
float[] myhist = new float[(end - start) / binsize + 1];
for (int i = 0; i < hits.size(); i++) {
if (hits.get(i) >= start && hits.get(i) <= end) {
myhist[(hits.get(i) - start) / binsize] += weights.get(i);
}
}
assertTrue(myhist.length == histogram.length);
for (int i = 0; i < myhist.length; i++) {
assertTrue(myhist[i] == histogram[i]);
}
}
}
public static void main(String args[]) {
prefix = args[0];
if (!prefix.endsWith(System.getProperty("file.separator"))) {
prefix = prefix + System.getProperty("file.separator");
}
chrom = Integer.parseInt(args[1]);
org.junit.runner.JUnitCore.main("org.seqcode.data.readdb.TestHits");
}
}