jpayne@68: package kmer; jpayne@68: jpayne@68: import java.io.PrintStream; jpayne@68: import java.util.ArrayList; jpayne@68: import java.util.Arrays; jpayne@68: import java.util.concurrent.ArrayBlockingQueue; jpayne@68: jpayne@68: import dna.AminoAcid; jpayne@68: import fileIO.FileFormat; jpayne@68: import fileIO.ReadWrite; jpayne@68: import fileIO.TextStreamWriter; jpayne@68: import jgi.BBMerge; jpayne@68: import shared.PreParser; jpayne@68: import shared.Shared; jpayne@68: import shared.Timer; jpayne@68: import shared.Tools; jpayne@68: import stream.ConcurrentReadInputStream; jpayne@68: import stream.Read; jpayne@68: import structures.IntList; jpayne@68: import structures.ListNum; jpayne@68: jpayne@68: /** jpayne@68: * @author Brian Bushnell jpayne@68: * @date Mar 4, 2015 jpayne@68: * jpayne@68: */ jpayne@68: public class TableLoaderLockFree { jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Initialization ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** jpayne@68: * Code entrance from the command line. jpayne@68: * @param args Command line arguments jpayne@68: */ jpayne@68: public static void main(String[] args){ jpayne@68: jpayne@68: {//Preparse block for help, config files, and outstream jpayne@68: PreParser pp=new PreParser(args, null, false); jpayne@68: args=pp.args; jpayne@68: outstream=pp.outstream; jpayne@68: } jpayne@68: jpayne@68: Timer t=new Timer(); jpayne@68: jpayne@68: AbstractKmerTable[] tables=makeTables(AbstractKmerTable.ARRAY1D, 12, -1L, false, 1.0); jpayne@68: jpayne@68: int k=31; jpayne@68: int mink=0; jpayne@68: int speed=0; jpayne@68: int hdist=0; jpayne@68: int edist=0; jpayne@68: boolean rcomp=true; jpayne@68: boolean maskMiddle=false; jpayne@68: jpayne@68: //Create a new Loader instance jpayne@68: TableLoaderLockFree loader=new TableLoaderLockFree(tables, k, mink, speed, hdist, edist, rcomp, maskMiddle); jpayne@68: loader.setRefSkip(0); jpayne@68: loader.hammingDistance2=0; jpayne@68: loader.editDistance2=0; jpayne@68: loader.storeMode(SET_IF_NOT_PRESENT); jpayne@68: jpayne@68: ///And run it jpayne@68: String[] refs=args; jpayne@68: String[] literals=null; jpayne@68: boolean keepNames=false; jpayne@68: boolean useRefNames=false; jpayne@68: long kmers=loader.processData(refs, literals, keepNames, useRefNames, false); jpayne@68: t.stop(); jpayne@68: jpayne@68: outstream.println("Time: \t"+t); jpayne@68: outstream.println("Return: \t"+kmers); jpayne@68: outstream.println("refKmers: \t"+loader.refKmers); jpayne@68: outstream.println("refBases: \t"+loader.refBases); jpayne@68: outstream.println("refReads: \t"+loader.refReads); jpayne@68: jpayne@68: //Close the print stream if it was redirected jpayne@68: Shared.closeStream(outstream); jpayne@68: } jpayne@68: jpayne@68: public TableLoaderLockFree(AbstractKmerTable[] tables_, int k_){ jpayne@68: this(tables_, k_, 0, 0, 0, 0, true, false); jpayne@68: } jpayne@68: jpayne@68: public TableLoaderLockFree(AbstractKmerTable[] tables_, int k_, int mink_, int speed_, int hdist_, int edist_, boolean rcomp_, boolean maskMiddle_){ jpayne@68: tables=tables_; jpayne@68: k=k_; jpayne@68: k2=k-1; jpayne@68: mink=mink_; jpayne@68: rcomp=rcomp_; jpayne@68: useShortKmers=(mink>0 && mink(); jpayne@68: refNames=new ArrayList(); jpayne@68: scaffoldLengths=new IntList(); jpayne@68: jpayne@68: if(ref!=null){ jpayne@68: for(String s : ref){refNames.add(s);} jpayne@68: } jpayne@68: if(literal!=null){refNames.add("literal");} jpayne@68: refScafCounts=new int[refNames.size()]; jpayne@68: jpayne@68: if(useRefNames){toRefNames();} jpayne@68: } jpayne@68: jpayne@68: return spawnLoadThreads(ref, literal); jpayne@68: } jpayne@68: jpayne@68: public void setRefSkip(int x){setRefSkip(x, x);} jpayne@68: jpayne@68: public void setRefSkip(int min, int max){ jpayne@68: max=Tools.max(min, max); jpayne@68: if(min==max){ jpayne@68: minRefSkip=maxRefSkip=min; jpayne@68: }else{ jpayne@68: minRefSkip=min; jpayne@68: maxRefSkip=max; jpayne@68: } jpayne@68: variableRefSkip=(minRefSkip!=maxRefSkip); jpayne@68: } jpayne@68: jpayne@68: public void storeMode(final int x){ jpayne@68: assert(x==SET_IF_NOT_PRESENT || x==SET_ALWAYS || x==INCREMENT); jpayne@68: storeMode=x; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Inner Methods ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: jpayne@68: /** jpayne@68: * Fills tables with kmers from references, using multiple LoadThread. jpayne@68: * @return Number of kmers stored. jpayne@68: */ jpayne@68: private long spawnLoadThreads(String[] ref, String[] literal){ jpayne@68: Timer t=new Timer(); jpayne@68: if((ref==null || ref.length<1) && (literal==null || literal.length<1)){return 0;} jpayne@68: long added=0; jpayne@68: jpayne@68: /* Create load threads */ jpayne@68: LoadThread[] loaders=new LoadThread[WAYS]; jpayne@68: for(int i=0; i ln=cris.nextList(); jpayne@68: ArrayList reads=(ln!=null ? ln.list : null); jpayne@68: jpayne@68: /* Iterate through read lists from the input stream */ jpayne@68: while(ln!=null && reads!=null && reads.size()>0){//ln!=null prevents a compiler potential null access warning jpayne@68: { jpayne@68: /* Assign a unique ID number to each scaffold */ jpayne@68: ArrayList reads2=new ArrayList(reads); jpayne@68: if(scaffoldNames!=null){ jpayne@68: for(Read r1 : reads2){ jpayne@68: final Read r2=r1.mate; jpayne@68: final Integer id=scaffoldNames.size(); jpayne@68: if(ecc && r1!=null && r2!=null){BBMerge.findOverlapStrict(r1, r2, true);} jpayne@68: refScafCounts[refNum]++; jpayne@68: scaffoldNames.add(r1.id==null ? id.toString() : r1.id); jpayne@68: int len=r1.length(); jpayne@68: r1.obj=id; jpayne@68: if(r2!=null){ jpayne@68: r2.obj=id; jpayne@68: len+=r2.length(); jpayne@68: } jpayne@68: scaffoldLengths.add(len); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: if(REPLICATE_AMBIGUOUS){ jpayne@68: reads2=Tools.replicateAmbiguous(reads2, Tools.min(k, mink)); jpayne@68: } jpayne@68: jpayne@68: /* Send a pointer to the read list to each LoadThread */ jpayne@68: for(LoadThread lt : loaders){ jpayne@68: boolean b=true; jpayne@68: while(b){ jpayne@68: try { jpayne@68: lt.queue.put(reads2); jpayne@68: b=false; jpayne@68: } catch (InterruptedException e) { jpayne@68: //TODO: This will hang due to still-running threads. jpayne@68: throw new RuntimeException(e); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /* Dispose of the old list and fetch a new one */ jpayne@68: cris.returnList(ln); jpayne@68: ln=cris.nextList(); jpayne@68: reads=(ln!=null ? ln.list : null); jpayne@68: } jpayne@68: /* Cleanup */ jpayne@68: cris.returnList(ln); jpayne@68: errorState|=ReadWrite.closeStream(cris); jpayne@68: refNum++; jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /* If there are literal sequences to use as references */ jpayne@68: if(literal!=null){ jpayne@68: ArrayList list=new ArrayList(literal.length); jpayne@68: if(verbose){outstream.println("Adding literals "+Arrays.toString(literal));} jpayne@68: jpayne@68: /* Assign a unique ID number to each literal sequence */ jpayne@68: for(int i=0; i "+name); jpayne@68: scaffoldNames.set(s, name); jpayne@68: s++; jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Inner Classes ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** jpayne@68: * Loads kmers into a table. Each thread handles all kmers X such that X%WAYS==tnum. jpayne@68: */ jpayne@68: private class LoadThread extends Thread{ jpayne@68: jpayne@68: public LoadThread(final int tnum_){ jpayne@68: tnum=tnum_; jpayne@68: map=tables[tnum]; jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * Get the next list of reads (or scaffolds) from the queue. jpayne@68: * @return List of reads jpayne@68: */ jpayne@68: private ArrayList fetch(){ jpayne@68: ArrayList list=null; jpayne@68: while(list==null){ jpayne@68: try { jpayne@68: list=queue.take(); jpayne@68: } catch (InterruptedException e) { jpayne@68: // TODO Auto-generated catch block jpayne@68: e.printStackTrace(); jpayne@68: } jpayne@68: } jpayne@68: return list; jpayne@68: } jpayne@68: jpayne@68: @Override jpayne@68: public void run(){ jpayne@68: ArrayList reads=fetch(); jpayne@68: while(reads!=POISON){ jpayne@68: for(Read r1 : reads){ jpayne@68: assert(r1.pairnum()==0); jpayne@68: final Read r2=r1.mate; jpayne@68: jpayne@68: addedT+=addToMap(r1, minRefSkip); jpayne@68: if(r2!=null){addedT+=addToMap(r2, minRefSkip);} jpayne@68: } jpayne@68: reads=fetch(); jpayne@68: } jpayne@68: jpayne@68: if(map.canRebalance() && map.size()>2L*map.arrayLength()){ jpayne@68: map.rebalance(); jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param r The current read to process jpayne@68: * @param skip Number of bases to skip between kmers jpayne@68: * @return Number of kmers stored jpayne@68: */ jpayne@68: private long addToMap(Read r, int skip){ jpayne@68: if(variableRefSkip){ jpayne@68: int rblen=r.length(); jpayne@68: skip=(rblen>20000000 ? k : rblen>5000000 ? 11 : rblen>500000 ? 2 : 0); jpayne@68: skip=Tools.mid(minRefSkip, maxRefSkip, skip); jpayne@68: } jpayne@68: final byte[] bases=r.bases; jpayne@68: final int shift=2*k; jpayne@68: final int shift2=shift-2; jpayne@68: final long mask=(shift>63 ? -1L : ~((-1L)<1){ //Process while skipping some kmers jpayne@68: for(int i=0; i>>2)|(x2<=mink; i--){ jpayne@68: kmer=kmer&rightMasks[i]; jpayne@68: rkmer=rkmer>>>2; jpayne@68: long x=addToMap(kmer, rkmer, i, extraBase, id, kMasks[i], hammingDistance2, editDistance2); jpayne@68: added+=x; jpayne@68: if(verbose){ jpayne@68: if((toValue(kmer, rkmer, kMasks[i]))%WAYS==tnum){ jpayne@68: outstream.println("added="+x+"; i="+i+"; tnum="+tnum+"; Added left-shift kmer "+AminoAcid.kmerToString(kmer&~kMasks[i], i)+"; value="+(toValue(kmer, rkmer, kMasks[i]))+"; kmer="+kmer+"; rkmer="+rkmer+"; kmask="+kMasks[i]+"; rightMasks[i+1]="+rightMasks[i+1]); jpayne@68: outstream.println("i="+i+"; tnum="+tnum+"; Looking for left-shift kmer "+AminoAcid.kmerToString(kmer&~kMasks[i], i)); jpayne@68: final long value=toValue(kmer, rkmer, kMasks[i]); jpayne@68: if(map.contains(value)){outstream.println("Found "+value);} jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: return added; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** jpayne@68: * Adds short kmers on the right end of the read. jpayne@68: * @param kmer Forward kmer jpayne@68: * @param rkmer Reverse kmer jpayne@68: * @param id Scaffold number jpayne@68: * @return Number of kmers stored jpayne@68: */ jpayne@68: private long addToMapRightShift(long kmer, long rkmer, final int id){ jpayne@68: if(verbose){outstream.println("addToMapRightShift");} jpayne@68: long added=0; jpayne@68: for(int i=k-1; i>=mink; i--){ jpayne@68: long extraBase=kmer&3L; jpayne@68: kmer=kmer>>>2; jpayne@68: rkmer=rkmer&rightMasks[i]; jpayne@68: // assert(Long.numberOfLeadingZeros(kmer)>=2*(32-i)) : Long.numberOfLeadingZeros(kmer)+", "+i+", "+kmer+", "+kMasks[i]; jpayne@68: // assert(Long.numberOfLeadingZeros(rkmer)>=2*(32-i)) : Long.numberOfLeadingZeros(rkmer)+", "+i+", "+rkmer+", "+kMasks[i]; jpayne@68: long x=addToMap(kmer, rkmer, i, extraBase, id, kMasks[i], hammingDistance2, editDistance2); jpayne@68: added+=x; jpayne@68: if(verbose){ jpayne@68: if((toValue(kmer, rkmer, kMasks[i]))%WAYS==tnum){ jpayne@68: outstream.println("added="+x+"; i="+i+"; tnum="+tnum+"; Added right-shift kmer "+AminoAcid.kmerToString(kmer&~kMasks[i], i)+"; value="+(toValue(kmer, rkmer, kMasks[i]))+"; kmer="+kmer+"; rkmer="+rkmer+"; kmask="+kMasks[i]+"; rightMasks[i+1]="+rightMasks[i+1]); jpayne@68: outstream.println("i="+i+"; tnum="+tnum+"; Looking for right-shift kmer "+AminoAcid.kmerToString(kmer&~kMasks[i], i)); jpayne@68: final long value=toValue(kmer, rkmer, kMasks[i]); jpayne@68: if(map.contains(value)){outstream.println("Found "+value);} jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: return added; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: /** jpayne@68: * Adds this kmer to the table, including any mutations implied by editDistance or hammingDistance. jpayne@68: * @param kmer Forward kmer jpayne@68: * @param rkmer Reverse kmer jpayne@68: * @param len Kmer length jpayne@68: * @param extraBase Base added to end in case of deletions jpayne@68: * @param id Scaffold number jpayne@68: * @param kmask0 jpayne@68: * @return Number of kmers stored jpayne@68: */ jpayne@68: private long addToMap(final long kmer, final long rkmer, final int len, final long extraBase, final int id, final long kmask0, final int hdist, final int edist){ jpayne@68: jpayne@68: assert(kmask0==kMasks[len]) : kmask0+", "+len+", "+kMasks[len]+", "+Long.numberOfTrailingZeros(kmask0)+", "+Long.numberOfTrailingZeros(kMasks[len]); jpayne@68: jpayne@68: if(verbose){outstream.println("addToMap_A; len="+len+"; kMasks[len]="+kMasks[len]);} jpayne@68: assert((kmer&kmask0)==0); jpayne@68: final long added; jpayne@68: if(hdist==0){ jpayne@68: final long key=toValue(kmer, rkmer, kmask0); jpayne@68: if(failsSpeed(key)){return 0;} jpayne@68: if(key%WAYS!=tnum){return 0;} jpayne@68: if(verbose){outstream.println("addToMap_B: "+AminoAcid.kmerToString(kmer&~kMasks[len], len)+" = "+key);} jpayne@68: if(storeMode==SET_IF_NOT_PRESENT){ jpayne@68: added=map.setIfNotPresent(key, id); jpayne@68: }else if(storeMode==SET_ALWAYS){ jpayne@68: added=map.set(key, id); jpayne@68: }else{ jpayne@68: assert(storeMode==INCREMENT); jpayne@68: added=map.increment(key, 1); jpayne@68: } jpayne@68: }else if(edist>0){ jpayne@68: // long extraBase=(i>=bases.length-1 ? -1 : AminoAcid.baseToNumber[bases[i+1]]); jpayne@68: added=mutate(kmer, rkmer, len, id, edist, extraBase); jpayne@68: }else{ jpayne@68: added=mutate(kmer, rkmer, len, id, hdist, -1); jpayne@68: } jpayne@68: if(verbose){outstream.println("addToMap added "+added+" keys.");} jpayne@68: return added; jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * Mutate and store this kmer through 'dist' recursions. jpayne@68: * @param kmer Forward kmer jpayne@68: * @param rkmer Reverse kmer jpayne@68: * @param id Scaffold number jpayne@68: * @param dist Number of mutations jpayne@68: * @param extraBase Base added to end in case of deletions jpayne@68: * @return Number of kmers stored jpayne@68: */ jpayne@68: private long mutate(final long kmer, final long rkmer, final int len, final int id, final int dist, final long extraBase){ jpayne@68: long added=0; jpayne@68: jpayne@68: final long key=toValue(kmer, rkmer, kMasks[len]); jpayne@68: jpayne@68: if(verbose){outstream.println("mutate_A; len="+len+"; kmer="+kmer+"; rkmer="+rkmer+"; kMasks[len]="+kMasks[len]);} jpayne@68: if(key%WAYS==tnum){ jpayne@68: if(verbose){outstream.println("mutate_B: "+AminoAcid.kmerToString(kmer&~kMasks[len], len)+" = "+key);} jpayne@68: int x; jpayne@68: if(storeMode==SET_IF_NOT_PRESENT){ jpayne@68: x=map.setIfNotPresent(key, id); jpayne@68: }else if(storeMode==SET_ALWAYS){ jpayne@68: x=map.set(key, id); jpayne@68: }else{ jpayne@68: assert(storeMode==INCREMENT); jpayne@68: x=map.increment(key, 1); jpayne@68: x=(x==1 ? 1 : 0); jpayne@68: } jpayne@68: if(verbose){outstream.println("mutate_B added "+x+" keys.");} jpayne@68: added+=x; jpayne@68: assert(map.contains(key)); jpayne@68: } jpayne@68: jpayne@68: if(dist>0){ jpayne@68: final int dist2=dist-1; jpayne@68: jpayne@68: //Sub jpayne@68: for(int j=0; j<4; j++){ jpayne@68: for(int i=0; i0){ jpayne@68: //Del jpayne@68: if(extraBase>=0 && extraBase<=3){ jpayne@68: for(int i=1; i>2); jpayne@68: for(int j=0; j<4; j++){ jpayne@68: final long temp=temp0|setMasks[j][i-1]; jpayne@68: if(temp!=kmer){ jpayne@68: long rtemp=AminoAcid.reverseComplementBinaryFast(temp, len); jpayne@68: added+=mutate(temp, rtemp, len, id, dist2, eb2); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: } jpayne@68: jpayne@68: return added; jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Number of kmers stored by this thread */ jpayne@68: public long addedT=0; jpayne@68: /** Number of items encountered by this thread */ jpayne@68: public long refKmersT=0, refReadsT=0, refBasesT=0; jpayne@68: /** Thread number; used to determine which kmers to store */ jpayne@68: public final int tnum; jpayne@68: /** Buffer of input read lists */ jpayne@68: public final ArrayBlockingQueue> queue=new ArrayBlockingQueue>(32); jpayne@68: jpayne@68: /** Destination for storing kmers */ jpayne@68: private final AbstractKmerTable map; jpayne@68: jpayne@68: } jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Static Methods ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** jpayne@68: * Transforms a kmer into a canonical value stored in the table. Expected to be inlined. jpayne@68: * @param kmer Forward kmer jpayne@68: * @param rkmer Reverse kmer jpayne@68: * @param lengthMask Bitmask with single '1' set to left of kmer jpayne@68: * @return Canonical value jpayne@68: */ jpayne@68: private final long toValue(long kmer, long rkmer, long lengthMask){ jpayne@68: assert(lengthMask==0 || (kmer=speed; jpayne@68: } jpayne@68: jpayne@68: final boolean failsSpeed(long key){ jpayne@68: return speed>0 && ((key&Long.MAX_VALUE)%17) scaffoldNames; jpayne@68: /** Names of reference files (refNames[0] is valid). */ jpayne@68: public ArrayList refNames; jpayne@68: /** Number of scaffolds per reference. */ jpayne@68: public int[] refScafCounts; jpayne@68: /** scaffoldLengths[id] stores the length of that scaffold */ jpayne@68: public IntList scaffoldLengths=new IntList(); jpayne@68: jpayne@68: /** Make the middle base in a kmer a wildcard to improve sensitivity */ jpayne@68: public final boolean maskMiddle=false; jpayne@68: /** Correct errors via read overlap */ jpayne@68: public boolean ecc=false; jpayne@68: jpayne@68: /** Store reference kmers with up to this many substitutions */ jpayne@68: public final int hammingDistance; jpayne@68: /** Store reference kmers with up to this many edits (including indels) */ jpayne@68: public final int editDistance; jpayne@68: /** Store short reference kmers with up to this many substitutions */ jpayne@68: public int hammingDistance2=-1; jpayne@68: /** Store short reference kmers with up to this many edits (including indels) */ jpayne@68: public int editDistance2=-1; jpayne@68: /** Always skip at least this many consecutive kmers when hashing reference. jpayne@68: * 1 means every kmer is used, 2 means every other, etc. */ jpayne@68: private int minRefSkip=0; jpayne@68: /** Never skip more than this many consecutive kmers when hashing reference. */ jpayne@68: private int maxRefSkip=0; jpayne@68: jpayne@68: private boolean variableRefSkip=false; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Statistics ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: long refReads=0; jpayne@68: long refBases=0; jpayne@68: long refKmers=0; jpayne@68: jpayne@68: long storedKmers=0; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Final Primitives ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Look for reverse-complements as well as forward kmers. Default: true */ jpayne@68: private final boolean rcomp; jpayne@68: /** AND bitmask with 0's at the middle base */ jpayne@68: private final long middleMask; jpayne@68: jpayne@68: /** Normal kmer length */ jpayne@68: private final int k; jpayne@68: /** k-1; used in some expressions */ jpayne@68: private final int k2; jpayne@68: /** Shortest kmer to use for trimming */ jpayne@68: private final int mink; jpayne@68: /** Attempt to match kmers shorter than normal k on read ends when doing kTrimming. */ jpayne@68: private final boolean useShortKmers; jpayne@68: jpayne@68: /** Fraction of kmers to skip, 0 to 16 out of 17 */ jpayne@68: private final int speed; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Static Fields ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: /** Default initial size of data structures */ jpayne@68: private static final int initialSizeDefault=128000; jpayne@68: jpayne@68: /** Number of tables (and threads, during loading) */ jpayne@68: private static final int WAYS=7; //123 jpayne@68: /** Verbose messages */ jpayne@68: public static final boolean verbose=false; //123 jpayne@68: jpayne@68: /** Print messages to this stream */ jpayne@68: private static PrintStream outstream=System.err; jpayne@68: /** Display progress messages such as memory usage */ jpayne@68: public static boolean DISPLAY_PROGRESS=true; jpayne@68: /** Indicates end of input stream */ jpayne@68: private static final ArrayList POISON=new ArrayList(0); jpayne@68: /** Make unambiguous copies of ref sequences with ambiguous bases */ jpayne@68: public static boolean REPLICATE_AMBIGUOUS=false; jpayne@68: jpayne@68: /** x&clearMasks[i] will clear base i */ jpayne@68: private static final long[] clearMasks; jpayne@68: /** x|setMasks[i][j] will set base i to j */ jpayne@68: private static final long[][] setMasks; jpayne@68: /** x&leftMasks[i] will clear all bases to the right of i (exclusive) */ jpayne@68: private static final long[] leftMasks; jpayne@68: /** x&rightMasks[i] will clear all bases to the left of i (inclusive) */ jpayne@68: private static final long[] rightMasks; jpayne@68: /** x|kMasks[i] will set the bit to the left of the leftmost base */ jpayne@68: private static final long[] kMasks; jpayne@68: jpayne@68: public static final int SET_IF_NOT_PRESENT=1, SET_ALWAYS=2, INCREMENT=3; jpayne@68: jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: /*---------------- Static Initializers ----------------*/ jpayne@68: /*--------------------------------------------------------------*/ jpayne@68: jpayne@68: static{ jpayne@68: clearMasks=new long[32]; jpayne@68: leftMasks=new long[32]; jpayne@68: rightMasks=new long[32]; jpayne@68: kMasks=new long[32]; jpayne@68: setMasks=new long[4][32]; jpayne@68: for(int i=0; i<32; i++){ jpayne@68: clearMasks[i]=~(3L<<(2*i)); jpayne@68: } jpayne@68: for(int i=0; i<32; i++){ jpayne@68: leftMasks[i]=((-1L)<<(2*i)); jpayne@68: } jpayne@68: for(int i=0; i<32; i++){ jpayne@68: rightMasks[i]=~((-1L)<<(2*i)); jpayne@68: } jpayne@68: for(int i=0; i<32; i++){ jpayne@68: kMasks[i]=((1L)<<(2*i)); jpayne@68: } jpayne@68: for(int i=0; i<32; i++){ jpayne@68: for(long j=0; j<4; j++){ jpayne@68: setMasks[(int)j][i]=(j<<(2*i)); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: }