/*Copyright (c) 2012 The Broad Institute *Permission is hereby granted, free of charge, to any person *obtaining a copy of this software and associated documentation *files (the "Software"), to deal in the Software without *restriction, including without limitation the rights to use, *copy, modify, merge, publish, distribute, sublicense, and/or sell *copies of the Software, and to permit persons to whom the *Software is furnished to do so, subject to the following *conditions: *The above copyright notice and this permission notice shall be *included in all copies or substantial portions of the Software. *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, *EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES *OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND *NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, *WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING *FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ import java.util.List; import java.util.LinkedList; import java.util.Map; import java.util.HashMap; import java.io.File; import java.util.Scanner; import java.io.IOException; import java.io.FileNotFoundException; import java.io.InputStreamReader; public class Sandbox { private long setupTime = 0; private long computeTime = 0; //Used to copy references to byteArrays to JNI from reads protected class JNIReadDataHolderClass { public byte[] readBases = null; public byte[] readQuals = null; public byte[] insertionGOP = null; public byte[] deletionGOP = null; public byte[] overallGCP = null; } //Used to copy references to byteArrays to JNI from haplotypes protected class JNIHaplotypeDataHolderClass { public byte[] haplotypeBases = null; } /** * Return 64-bit mask representing machine capabilities * Bit 0 is LSB, bit 63 MSB * Bit 0 represents sse4.2 availability * Bit 1 represents AVX availability */ public native long jniGetMachineType(); public static final long enableAll = 0xFFFFFFFFFFFFFFFFl; /** * Function to initialize the fields of JNIReadDataHolderClass and JNIHaplotypeDataHolderClass from JVM. * C++ codegets FieldIDs for these classes once and re-uses these IDs for the remainder of the program. Field IDs do not * change per JVM session * @param readDataHolderClass class type of JNIReadDataHolderClass * @param haplotypeDataHolderClass class type of JNIHaplotypeDataHolderClass * @param mask mask is a 64 bit integer identical to the one received from jniGetMachineType(). Users can disable usage of some hardware features by zeroing some bits in the mask * */ private native void jniInitializeClassFieldsAndMachineMask(Class readDataHolderClass, Class haplotypeDataHolderClass, long mask); private static Boolean isVectorLoglessPairHMMLibraryLoaded = false; //The constructor is called only once inside PairHMMLikelihoodCalculationEngine public Sandbox() { synchronized(isVectorLoglessPairHMMLibraryLoaded) { //Load the library and initialize the FieldIDs if(!isVectorLoglessPairHMMLibraryLoaded) { System.loadLibrary("VectorLoglessPairHMM"); isVectorLoglessPairHMMLibraryLoaded = true; jniInitializeClassFieldsAndMachineMask(JNIReadDataHolderClass.class, JNIHaplotypeDataHolderClass.class, enableAll); //need to do this only once } } } private native void jniInitializeHaplotypes(final int numHaplotypes, JNIHaplotypeDataHolderClass[] haplotypeDataArray); //Used to transfer data to JNI //Since the haplotypes are the same for all calls to computeLikelihoods within a region, transfer the haplotypes only once to the JNI per region public void initialize(final List haplotypes) { int numHaplotypes = haplotypes.size(); JNIHaplotypeDataHolderClass[] haplotypeDataArray = new JNIHaplotypeDataHolderClass[numHaplotypes]; int idx = 0; for(final JNIHaplotypeDataHolderClass currHaplotype : haplotypes) { haplotypeDataArray[idx] = new JNIHaplotypeDataHolderClass(); haplotypeDataArray[idx].haplotypeBases = currHaplotype.haplotypeBases; ++idx; } jniInitializeHaplotypes(numHaplotypes, haplotypeDataArray); } /** * Tell JNI to release arrays - really important if native code is directly accessing Java memory, if not * accessing Java memory directly, still important to release memory from C++ */ private native void jniFinalizeRegion(); public void finalizeRegion() { jniFinalizeRegion(); } /** * Real compute kernel */ private native void jniComputeLikelihoods(int numReads, int numHaplotypes, JNIReadDataHolderClass[] readDataArray, JNIHaplotypeDataHolderClass[] haplotypeDataArray, double[] likelihoodArray, int maxNumThreadsToUse); public void computeLikelihoods(final List reads, final List haplotypes) { //System.out.println("Region : "+reads.size()+" x "+haplotypes.size()); long startTime = System.nanoTime(); int readListSize = reads.size(); int numHaplotypes = haplotypes.size(); int numTestcases = readListSize*numHaplotypes; JNIReadDataHolderClass[] readDataArray = new JNIReadDataHolderClass[readListSize]; int idx = 0; for(JNIReadDataHolderClass read : reads) { readDataArray[idx] = new JNIReadDataHolderClass(); readDataArray[idx].readBases = read.readBases; readDataArray[idx].readQuals = read.readQuals; readDataArray[idx].insertionGOP = read.insertionGOP; readDataArray[idx].deletionGOP = read.deletionGOP; readDataArray[idx].overallGCP = read.overallGCP; ++idx; } double[] mLikelihoodArray = new double[readListSize*numHaplotypes]; //to store results setupTime += (System.nanoTime() - startTime); //for(reads) // for(haplotypes) // compute_full_prob() jniComputeLikelihoods(readListSize, numHaplotypes, readDataArray, null, mLikelihoodArray, 12); computeTime += (System.nanoTime() - startTime); } /** * Print final profiling information from native code */ public native void jniClose(); public void close() { System.out.println("Time spent in setup for JNI call : "+(setupTime*1e-9)+" compute time : "+(computeTime*1e-9)); jniClose(); } public void parseSandboxFile(String filename) { File file = new File(filename); Scanner input = null; try { input = new Scanner(file); } catch(FileNotFoundException e) { System.err.println("File "+filename+" cannot be found/read"); return; } int idx = 0; int numReads = 0; int numHaplotypes = 0; int readIdx = 0, testCaseIdx = 0, haplotypeIdx = 0; LinkedList haplotypeList = new LinkedList(); LinkedList readList = new LinkedList(); byte[][] byteArray = new byte[6][]; boolean firstLine = true; String[] currTokens = new String[8]; while(input.hasNextLine()) { String line = input.nextLine(); Scanner lineScanner = new Scanner(line); idx = 0; while(lineScanner.hasNext()) currTokens[idx++] = lineScanner.next(); if(idx == 0) break; assert(idx >= 6); //start of new region if(idx == 8) { if(!firstLine) { initialize(haplotypeList); computeLikelihoods(readList, haplotypeList); finalizeRegion(); } try { numReads = Integer.parseInt(currTokens[6]); } catch(NumberFormatException e) { numReads = 1; } try { numHaplotypes = Integer.parseInt(currTokens[7]); } catch(NumberFormatException e) { numHaplotypes = 1; } haplotypeIdx = readIdx = testCaseIdx = 0; readList.clear(); haplotypeList.clear(); } if(haplotypeIdx < numHaplotypes) { JNIHaplotypeDataHolderClass X = new JNIHaplotypeDataHolderClass(); X.haplotypeBases = currTokens[0].getBytes(); haplotypeList.add(X); } if(testCaseIdx%numHaplotypes == 0) { JNIReadDataHolderClass X = new JNIReadDataHolderClass(); X.readBases = currTokens[1].getBytes(); for(int i=2;i<6;++i) { byteArray[i] = currTokens[i].getBytes(); for(int j=0;j 0 && readList.size() > 0) { initialize(haplotypeList); computeLikelihoods(readList, haplotypeList); finalizeRegion(); } close(); input.close(); } private native void doEverythingNative(String filename); public static void main(String[] args) { if(args.length <= 0) { System.err.println("Needs 1 argument - "); System.exit(-1); } //// Get runtime //java.lang.Runtime rt = java.lang.Runtime.getRuntime(); //// Start a new process: UNIX command ls //String cmd = "/home/karthikg/broad/gsa-unstable/public/c++/VectorPairHMM/checker "+args[0]; //try //{ //System.out.println(cmd); //java.lang.Process p = rt.exec(cmd); //try //{ //p.waitFor(); //java.io.InputStream is = p.getInputStream(); //java.io.BufferedReader reader = new java.io.BufferedReader(new InputStreamReader(is)); //// And print each line //String s = null; //while ((s = reader.readLine()) != null) { //System.out.println(s); //} //is.close(); //} //catch(InterruptedException e) //{ //System.err.println(e); //} //} //catch(IOException e) //{ //System.err.println(e); //} Sandbox t = new Sandbox(); //t.doEverythingNative(args[0]); t.parseSandboxFile(args[0]); } }