package evoker;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.zip.GZIPInputStream;
public class GenfileDataFile extends BinaryDataFile{
GenfileDataFile(String filename, int numInds, MarkerData md, String collection, String chromosome) throws IOException{
super(filename, numInds, md, collection, chromosome);
// there are 3 four byte values for each ind in the ox format files
bytesPerRecord = 3 * 4 * numInds;
checkFile(bedMagic);
}
GenfileDataFile(String filename, int numInds, MarkerData md, String collection, boolean zipped, String chromosome) throws IOException{
super(filename, numInds, md, collection, chromosome);
// there are 3 four byte values for each ind in the ox format files
bytesPerRecord = 3 * 4 * numInds;
compressed = true;
// set the header offset here for now as it would normally be set in the checkfile method
bedHeaderOffset = 8;
// compressed file - do not use checkFile()
// TODO: method for checking compressed files
}
public ArrayList<Byte> getRecord(long snpIndex) throws IOException{
//have index, now load gen file
BufferedInputStream genIS;
ArrayList<Byte> genos = new ArrayList<Byte>();
if (this.isCompressed()){
genIS = new BufferedInputStream(new GZIPInputStream(new FileInputStream(file),8192));
} else{
genIS = new BufferedInputStream(new FileInputStream(file),8192);
}
//skip to SNP of interest
//sometimes the skip() method doesn't skip as far as you ask, so you have to keep flogging it
//java sux.
long remaining = (snpIndex * bytesPerRecord)+bedHeaderOffset;
while ((remaining = remaining - genIS.skip(remaining)) > 0){
}
//read raw snp data
byte[] binSnpData = new byte[bytesPerRecord];
genIS.read(binSnpData, 0, bytesPerRecord);
// close the input stream
genIS.close();
// convert the binary data array into a float array
float[] floatSnpData = new float[numInds*3];
int count = 0;
for (int start = 0; start < bytesPerRecord; start = start + 4) {
floatSnpData[count] = arr2float(binSnpData, start);
count++;
}
// loop through each set of three values and then decide on the genotype
for (int loop = 0; loop < floatSnpData.length; loop = loop + 3) {
float aa = floatSnpData[loop];
float ab = floatSnpData[loop+1];
float bb = floatSnpData[loop+2];
//convert into array of genotypes
//genotype code is:
//0 == homo 1
//1 == missing
//2 == hetero
//3 == homo 2
if (aa > 0.9) {
genos.add((byte)0);
} else if (ab >0.9){
genos.add((byte)2);
} else if (bb > 0.9) {
genos.add((byte)3);
} else {
genos.add((byte)1);
}
}
return genos;
}
public static float arr2float (byte[] arr, int start) {
int i = 0;
int len = 4;
int cnt = 0;
byte[] tmp = new byte[len];
for (i = start; i < (start + len); i++) {
tmp[cnt] = arr[i];
cnt++;
}
int accum = 0;
i = 0;
for ( int shiftBy = 0; shiftBy < 32; shiftBy += 8 ) {
accum |= ( (long)( tmp[i] & 0xff ) ) << shiftBy;
i++;
}
return Float.intBitsToFloat(accum);
}
}