package evoker; import java.io.File; import java.io.IOException; import java.io.BufferedInputStream; import java.io.FileInputStream; import java.math.BigInteger; import java.nio.ByteBuffer; import java.nio.ByteOrder; import java.util.ArrayList; public abstract class BinaryDataFile extends BinaryData{ File file; protected boolean compressed; BinaryDataFile(String filename, int numInds, MarkerData md, String collection, String chromosome){ super(numInds,md,collection, chromosome); this.file = new File(filename); } /** * Checks whether the file is of a valid format * * @param headers * @throws IOException */ public void checkFile(byte[] headers) throws IOException{ if (file != null){ BigInteger fileSize = BigInteger.valueOf(file.length()); BigInteger checkSize = BigInteger.valueOf(new Long(numSNPs)).multiply(BigInteger.valueOf(new Long(bytesPerRecord))); if (!fileSize.equals(checkSize.add(BigInteger.valueOf(new Long(headers.length))))) { if (fileSize.equals(checkSize.add(new BigInteger("8")))){ //alternate Oxford format //Change headers byte[] to be a new byte[] of the correct things as specified by numSNPs and numInds. ByteBuffer buf = ByteBuffer.allocate(8); buf.order(ByteOrder.LITTLE_ENDIAN); // in the case of remote data we need to compare the total snps as this is the value in the header buf.putInt(this.totNumSNPs); if (file.getName().endsWith("bed") || file.getName().endsWith("gen.bin") ){ // the inds value in the header is the number of columns--three values per ind buf.putInt(this.numInds*3); }else if (file.getName().endsWith("bnt") || file.getName().endsWith("int.bin")){ // the inds value in the header is the number of columns--two values per ind buf.putInt(this.numInds*2); } buf.clear(); headers = new byte[8]; buf.get(headers, 0, 8); bntHeaderOffset = 8; bedHeaderOffset = 8; } else{ throw new IOException(file + " is not properly formatted.\n(Incorrect length.)"); } } } else{ //this is a useless message, but it implies badness 10000 throw new IOException("File is null?!?"); } //are the headers acceptable for this file? BufferedInputStream binaryIS = new BufferedInputStream(new FileInputStream(file),8192); byte[] fromFile = new byte[headers.length]; binaryIS.read(fromFile,0,headers.length); for (int i = 0; i < headers.length; i++){ if (fromFile[i] != headers[i]){ throw new IOException(file + " is not properly formatted.\n(Magic number is incorrect.)"); } } } public void checkFile(byte[] headers, boolean zipped) throws IOException{ //TODO: method for checking if compressed files are valid evoker files // get the uncompressed size of the file - for gzip files that where originally smaller than 4gb you can read the last 4 bytes of the file // at the moment we can assume this type of file is Oxford format } public ArrayList getRecord(String markerName){ //do some checks on getting the data and handle errors centrally int snpIndex; try { if((snpIndex = md.getIndex(markerName,md.getSampleCollectionIndex(collection))) >= 0) { return getRecord(snpIndex); } }catch(IOException ioe) { //TODO: handle me //TODO: I don't know anything about that SNP? } return(null); } public boolean isCompressed(){ return compressed; } abstract ArrayList getRecord(long index) throws IOException; }