jpayne@68: package bloom; jpayne@68: jpayne@68: import java.io.Serializable; jpayne@68: import java.util.Locale; jpayne@68: import java.util.concurrent.atomic.AtomicInteger; jpayne@68: import java.util.concurrent.atomic.AtomicIntegerArray; jpayne@68: jpayne@68: import dna.AminoAcid; jpayne@68: import shared.Shared; jpayne@68: import shared.Tools; jpayne@68: import structures.ByteBuilder; jpayne@68: jpayne@68: /** jpayne@68: * @author Brian Bushnell jpayne@68: * @date Jul 5, 2012 jpayne@68: */ jpayne@68: public abstract class KCountArray implements Serializable { jpayne@68: jpayne@68: /** jpayne@68: * jpayne@68: */ jpayne@68: private static final long serialVersionUID = 1590374813059942002L; jpayne@68: jpayne@68: public static KCountArray makeNew(long cells_, int cbits_){ jpayne@68: return makeNew(cells_, cbits_, 1); jpayne@68: } jpayne@68: jpayne@68: public static KCountArray makeNew(long cells_, int cbits_, int hashes_){ jpayne@68: return makeNew(cells_, cbits_, hashes_, null, 0); jpayne@68: } jpayne@68: jpayne@68: //TODO: Get rid of keys_ arg. jpayne@68: public static KCountArray makeNew(long cells_, int cbits_, int hashes_, KCountArray prefilter, int prefilterLimit_){ jpayne@68: KCountArray kca=new KCountArray7MTA(cells_, cbits_, hashes_, prefilter, prefilterLimit_); jpayne@68: kca.initialize(); jpayne@68: return kca; jpayne@68: } jpayne@68: jpayne@68: protected KCountArray(final long cells_, int cbits_){ jpayne@68: assert(cbits_<=32); jpayne@68: assert(Integer.bitCount(cbits_)==1); jpayne@68: assert(Long.bitCount(cells_)==1) || this.getClass()==KCountArray7MT.class : this.getClass(); jpayne@68: jpayne@68: numArrays=64; jpayne@68: arrayBits=31-Integer.numberOfLeadingZeros(numArrays); jpayne@68: arrayMask=numArrays-1; jpayne@68: jpayne@68: while(cbits_*cells_<32*numArrays){ jpayne@68: assert(false) : cells_+", "+cbits_+", "+numArrays+", "+(cbits_*cells_)+"<"+(32*numArrays); jpayne@68: cbits_*=2; jpayne@68: } //Increases bits per cell so that at minimum each array is size 1 jpayne@68: jpayne@68: assert(cbits_<=32); jpayne@68: jpayne@68: cells=cells_; jpayne@68: cellBits=cbits_; jpayne@68: valueMask=(cellBits==32 ? Integer.MAX_VALUE : ~((-1)<=b){return b;} jpayne@68: int c=readRight(key, k, makeCanonical); jpayne@68: if(c>=b){return b;} jpayne@68: return (int)(((long)a+(long)c)/2); jpayne@68: // return max(a, c); jpayne@68: // int mid=Tools.min(a, b, c); jpayne@68: // System.out.println("a="+a+", b="+b+", c="+c+" -> "+mid); jpayne@68: // return mid; jpayne@68: } jpayne@68: jpayne@68: public final int readPreciseMin(long key, int k, boolean makeCanonical){ jpayne@68: assert(k<=32); jpayne@68: int b=read(makeCanonical ? makeCanonical2(key, k) : key); jpayne@68: if(b<1){return b;} jpayne@68: int a=readLeft(key, k, makeCanonical); jpayne@68: if(a<1){return a;} jpayne@68: int c=readRight(key, k, makeCanonical); jpayne@68: return Tools.min(a, b, c); jpayne@68: } jpayne@68: jpayne@68: /** jpayne@68: * @param key Kmer to evaluate jpayne@68: * @return Sum of counts of all 4 possible left-adjacent kmers jpayne@68: */ jpayne@68: public int readLeft(long key, int k, boolean makeCanonical){throw new RuntimeException("Unsupported.");} jpayne@68: /** jpayne@68: * @param key Kmer to evaluate jpayne@68: * @return Sum of counts of all 4 possible right-adjacent kmers jpayne@68: */ jpayne@68: public int readRight(long key, int k, boolean makeCanonical){throw new RuntimeException("Unsupported.");} jpayne@68: /** jpayne@68: * @param key Kmer to evaluate jpayne@68: * @return Array of counts of all 4 possible left-adjacent kmers jpayne@68: */ jpayne@68: public int[] readAllLeft(final long key, final int k, boolean makeCanonical, int[] rvec){throw new RuntimeException("Unsupported.");} jpayne@68: /** jpayne@68: * @param key Kmer to evaluate jpayne@68: * @return Array of counts of all 4 possible right-adjacent kmers jpayne@68: */ jpayne@68: public int[] readAllRight(final long key, final int k, boolean makeCanonical, int[] rvec){throw new RuntimeException("Unsupported.");} jpayne@68: jpayne@68: public void increment(long[] keys){ jpayne@68: synchronized(this){ jpayne@68: for(long key : keys){ jpayne@68: increment(key); jpayne@68: } jpayne@68: } jpayne@68: } jpayne@68: jpayne@68: public abstract long[] transformToFrequency(); jpayne@68: public final long[] transformToFrequency(int[][] matrix){ jpayne@68: long[] freq=new long[100000]; jpayne@68: int maxFreq=freq.length-1; jpayne@68: jpayne@68: if(cellBits!=32){ jpayne@68: assert(cellBits>0); jpayne@68: for(int[] array : matrix){ jpayne@68: for(int i=0; i10000000000L){ jpayne@68: div=1000000000L; jpayne@68: ext="B"; jpayne@68: }else if(x>10000000){ jpayne@68: div=1000000; jpayne@68: ext="M"; jpayne@68: }else if(x>100000){ jpayne@68: div=1000; jpayne@68: ext="K"; jpayne@68: } jpayne@68: return String.format(Locale.ROOT, "%.2f", x/div)+ext; jpayne@68: } jpayne@68: jpayne@68: static final AtomicIntegerArray[] allocMatrix(final int numArrays, final int wordsPerArray){ jpayne@68: final AtomicIntegerArray[] matrix=new AtomicIntegerArray[numArrays]; jpayne@68: final AllocThread[] array=new AllocThread[Tools.min(Tools.max(Shared.threads()/2, 1), numArrays)]; jpayne@68: final AtomicInteger next=new AtomicInteger(0); jpayne@68: for(int i=0; iy ? x : y;} jpayne@68: public static final long min(long x, long y){return xy ? x : y;} jpayne@68: jpayne@68: /** Any necessary initialization. */ jpayne@68: public void initialize(){} jpayne@68: jpayne@68: /** Any necessary shutdown steps. */ jpayne@68: public void shutdown(){} jpayne@68: jpayne@68: public final long cells; jpayne@68: public final int cellBits; jpayne@68: /** Originally this was different than valueMask in the case that valueMask was negative, but now they are the same. */ jpayne@68: public final int maxValue; jpayne@68: jpayne@68: protected final int cellsPerWord; jpayne@68: protected final int indexShift; jpayne@68: protected final int cellMask; jpayne@68: protected final int valueMask; jpayne@68: jpayne@68: protected static int minArrays=calcMinArrays(); jpayne@68: protected final int arrayBits; jpayne@68: protected final int numArrays; jpayne@68: protected final int arrayMask; jpayne@68: jpayne@68: public static boolean verbose=false; jpayne@68: jpayne@68: private static final int calcMinArrays(){ jpayne@68: int x=Tools.max(Shared.threads(), 2); jpayne@68: while(Integer.bitCount(x)!=1){x++;} jpayne@68: return x; jpayne@68: } jpayne@68: jpayne@68: public static final boolean isCanonical(long key, int k){ jpayne@68: assert(k>3 && k<=32); jpayne@68: long b=AminoAcid.reverseComplementBinaryFast(key, k); jpayne@68: return key>=b; jpayne@68: } jpayne@68: jpayne@68: /** Assumes that the key is not canonical */ jpayne@68: public static final long makeCanonical(final long key, final int k){ jpayne@68: assert(k>3 && k<=32); jpayne@68: // assert(!isCanonical(key, k)); jpayne@68: final long r=AminoAcid.reverseComplementBinaryFast(key, k); jpayne@68: assert(r>=key); jpayne@68: // assert(isCanonical(r, k)); jpayne@68: // assert(AminoAcid.reverseComplementBinaryFast(r, k)==key); jpayne@68: return r; jpayne@68: } jpayne@68: jpayne@68: jpayne@68: public static final long makeCanonical2(final long key, final int k){ jpayne@68: assert(k>3 && k<=32); jpayne@68: if(isCanonical(key, k)){return key;} jpayne@68: long r=AminoAcid.reverseComplementBinaryFast(key, k); jpayne@68: // assert(isCanonical(r, k)) : k+"\n"+Long.toBinaryString(key)+"\n"+Long.toBinaryString(r)+"\n"+Long.toBinaryString(AminoAcid.reverseComplementBinaryFast(r, k)); jpayne@68: // assert(AminoAcid.reverseComplementBinaryFast(r, k)==key) : k+"\n"+Long.toBinaryString(key)+"\n"+Long.toBinaryString(r)+"\n"+Long.toBinaryString(AminoAcid.reverseComplementBinaryFast(r, k)); jpayne@68: return r; jpayne@68: } jpayne@68: jpayne@68: public KCountArray prefilter(){ jpayne@68: throw new RuntimeException("TODO: Override"); jpayne@68: } jpayne@68: jpayne@68: public void purgeFilter(){ jpayne@68: throw new RuntimeException("TODO: Override"); jpayne@68: } jpayne@68: jpayne@68: /** Increases accuracy of overloaded multi-bit tables */ jpayne@68: public static boolean LOCKED_INCREMENT=false; jpayne@68: public static boolean SET_LOCKED_INCREMENT=false; jpayne@68: jpayne@68: }