jpayne@68
|
1 package kmer;
|
jpayne@68
|
2
|
jpayne@68
|
3 import java.util.concurrent.atomic.AtomicLong;
|
jpayne@68
|
4
|
jpayne@68
|
5 import fileIO.ByteStreamWriter;
|
jpayne@68
|
6 import fileIO.TextStreamWriter;
|
jpayne@68
|
7 import structures.ByteBuilder;
|
jpayne@68
|
8 import structures.SuperLongList;
|
jpayne@68
|
9
|
jpayne@68
|
10 /**
|
jpayne@68
|
11 * @author Brian Bushnell
|
jpayne@68
|
12 * @date Nov 22, 2013
|
jpayne@68
|
13 *
|
jpayne@68
|
14 */
|
jpayne@68
|
15 public class HashBuffer extends AbstractKmerTable {
|
jpayne@68
|
16
|
jpayne@68
|
17 /*--------------------------------------------------------------*/
|
jpayne@68
|
18 /*---------------- Initialization ----------------*/
|
jpayne@68
|
19 /*--------------------------------------------------------------*/
|
jpayne@68
|
20
|
jpayne@68
|
21 public HashBuffer(AbstractKmerTable[] tables_, int buflen_, int k_, boolean initValues, boolean setIfNotPresent_){
|
jpayne@68
|
22 tables=tables_;
|
jpayne@68
|
23 buflen=buflen_;
|
jpayne@68
|
24 halflen=(int)Math.ceil(buflen*0.5);
|
jpayne@68
|
25 ways=tables.length;
|
jpayne@68
|
26 buffers=new KmerBuffer[ways];
|
jpayne@68
|
27 setIfNotPresent=setIfNotPresent_;
|
jpayne@68
|
28 useValues=initValues;
|
jpayne@68
|
29 coreMask=(AbstractKmerTableSet.MASK_CORE ? ~(((-1L)<<(2*(k_-1)))|3) : -1L);
|
jpayne@68
|
30 for(int i=0; i<ways; i++){
|
jpayne@68
|
31 buffers[i]=new KmerBuffer(buflen, k_, useValues);
|
jpayne@68
|
32 }
|
jpayne@68
|
33 }
|
jpayne@68
|
34
|
jpayne@68
|
35 /*--------------------------------------------------------------*/
|
jpayne@68
|
36 /*---------------- Public Methods ----------------*/
|
jpayne@68
|
37 /*--------------------------------------------------------------*/
|
jpayne@68
|
38
|
jpayne@68
|
39 public final int kmerToWay(final long kmer){
|
jpayne@68
|
40 final int way=(int)((kmer&coreMask)%ways);
|
jpayne@68
|
41 return way;
|
jpayne@68
|
42 }
|
jpayne@68
|
43
|
jpayne@68
|
44 @Override
|
jpayne@68
|
45 public int incrementAndReturnNumCreated(final long kmer, final int incr) {
|
jpayne@68
|
46 assert(incr==1); //I could just add the kmer multiple times if not true, with addMulti
|
jpayne@68
|
47 final int way=kmerToWay(kmer);
|
jpayne@68
|
48 KmerBuffer buffer=buffers[way];
|
jpayne@68
|
49 // final int size=buffer.addMulti(kmer, incr);
|
jpayne@68
|
50 final int size=buffer.add(kmer);
|
jpayne@68
|
51 if(size>=halflen && (size>=buflen || (size&SIZEMASK)==0)){
|
jpayne@68
|
52 return dumpBuffer(way, size>=buflen);
|
jpayne@68
|
53 }
|
jpayne@68
|
54 return 0;
|
jpayne@68
|
55 }
|
jpayne@68
|
56
|
jpayne@68
|
57 @Override
|
jpayne@68
|
58 public final long flush(){
|
jpayne@68
|
59 long added=0;
|
jpayne@68
|
60 for(int i=0; i<ways; i++){added+=dumpBuffer(i, true);}
|
jpayne@68
|
61 return added;
|
jpayne@68
|
62 }
|
jpayne@68
|
63
|
jpayne@68
|
64 @Override
|
jpayne@68
|
65 public int set(long kmer, int value) {
|
jpayne@68
|
66 final int way=kmerToWay(kmer);
|
jpayne@68
|
67 KmerBuffer buffer=buffers[way];
|
jpayne@68
|
68 final int size=buffer.add(kmer, value);
|
jpayne@68
|
69 if(size>=halflen && (size>=buflen || (size&SIZEMASK)==0)){
|
jpayne@68
|
70 return dumpBuffer(way, size>=buflen);
|
jpayne@68
|
71 }
|
jpayne@68
|
72 return 0;
|
jpayne@68
|
73 }
|
jpayne@68
|
74
|
jpayne@68
|
75 @Override
|
jpayne@68
|
76 public int set(long kmer, int[] vals, int vlen) {
|
jpayne@68
|
77 throw new RuntimeException("Unimplemented method; this class lacks value buffers");
|
jpayne@68
|
78 }
|
jpayne@68
|
79
|
jpayne@68
|
80 @Override
|
jpayne@68
|
81 public int setIfNotPresent(long kmer, int value) {
|
jpayne@68
|
82 throw new RuntimeException("Unimplemented method; this class lacks value buffers");
|
jpayne@68
|
83 }
|
jpayne@68
|
84
|
jpayne@68
|
85 @Override
|
jpayne@68
|
86 public int getValue(long kmer) {
|
jpayne@68
|
87 final int way=kmerToWay(kmer);
|
jpayne@68
|
88 return tables[way].getValue(kmer);
|
jpayne@68
|
89 }
|
jpayne@68
|
90
|
jpayne@68
|
91 @Override
|
jpayne@68
|
92 public int[] getValues(long kmer, int[] singleton){
|
jpayne@68
|
93 final int way=kmerToWay(kmer);
|
jpayne@68
|
94 return tables[way].getValues(kmer, singleton);
|
jpayne@68
|
95 }
|
jpayne@68
|
96
|
jpayne@68
|
97 @Override
|
jpayne@68
|
98 public boolean contains(long kmer) {
|
jpayne@68
|
99 final int way=kmerToWay(kmer);
|
jpayne@68
|
100 return tables[way].contains(kmer);
|
jpayne@68
|
101 }
|
jpayne@68
|
102
|
jpayne@68
|
103
|
jpayne@68
|
104
|
jpayne@68
|
105 /*--------------------------------------------------------------*/
|
jpayne@68
|
106 /*---------------- Ownership ----------------*/
|
jpayne@68
|
107 /*--------------------------------------------------------------*/
|
jpayne@68
|
108
|
jpayne@68
|
109 @Override
|
jpayne@68
|
110 public final void initializeOwnership(){
|
jpayne@68
|
111 for(AbstractKmerTable t : tables){t.initializeOwnership();}
|
jpayne@68
|
112 }
|
jpayne@68
|
113
|
jpayne@68
|
114 @Override
|
jpayne@68
|
115 public final void clearOwnership(){
|
jpayne@68
|
116 for(AbstractKmerTable t : tables){t.clearOwnership();}
|
jpayne@68
|
117 }
|
jpayne@68
|
118
|
jpayne@68
|
119 @Override
|
jpayne@68
|
120 public final int setOwner(final long kmer, final int newOwner){
|
jpayne@68
|
121 final int way=kmerToWay(kmer);
|
jpayne@68
|
122 return tables[way].setOwner(kmer, newOwner);
|
jpayne@68
|
123 }
|
jpayne@68
|
124
|
jpayne@68
|
125 @Override
|
jpayne@68
|
126 public final boolean clearOwner(final long kmer, final int owner){
|
jpayne@68
|
127 final int way=kmerToWay(kmer);
|
jpayne@68
|
128 return tables[way].clearOwner(kmer, owner);
|
jpayne@68
|
129 }
|
jpayne@68
|
130
|
jpayne@68
|
131 @Override
|
jpayne@68
|
132 public final int getOwner(final long kmer){
|
jpayne@68
|
133 final int way=kmerToWay(kmer);
|
jpayne@68
|
134 return tables[way].getOwner(kmer);
|
jpayne@68
|
135 }
|
jpayne@68
|
136
|
jpayne@68
|
137 /*--------------------------------------------------------------*/
|
jpayne@68
|
138 /*---------------- Nonpublic Methods ----------------*/
|
jpayne@68
|
139 /*--------------------------------------------------------------*/
|
jpayne@68
|
140
|
jpayne@68
|
141 @Override
|
jpayne@68
|
142 Object get(long kmer) {
|
jpayne@68
|
143 final int way=kmerToWay(kmer);
|
jpayne@68
|
144 return tables[way].get(kmer);
|
jpayne@68
|
145 }
|
jpayne@68
|
146
|
jpayne@68
|
147 /*--------------------------------------------------------------*/
|
jpayne@68
|
148 /*---------------- Private Methods ----------------*/
|
jpayne@68
|
149 /*--------------------------------------------------------------*/
|
jpayne@68
|
150
|
jpayne@68
|
151 private int dumpBuffer(final int way, boolean force){
|
jpayne@68
|
152 final KmerBuffer buffer=buffers[way];
|
jpayne@68
|
153 final AbstractKmerTable table=tables[way];
|
jpayne@68
|
154 final int lim=buffer.size();
|
jpayne@68
|
155 if(lim<0){return 0;}
|
jpayne@68
|
156
|
jpayne@68
|
157 if(force){table.lock();}
|
jpayne@68
|
158 else if(!table.tryLock()){return 0;}
|
jpayne@68
|
159
|
jpayne@68
|
160 if(SORT_BUFFERS && buffer.values==null){//Can go before or after lock; neither helps much
|
jpayne@68
|
161 buffer.kmers.sortSerial();
|
jpayne@68
|
162 }
|
jpayne@68
|
163
|
jpayne@68
|
164 final int x=dumpBuffer_inner(way);
|
jpayne@68
|
165 table.unlock();
|
jpayne@68
|
166 return x;
|
jpayne@68
|
167 }
|
jpayne@68
|
168
|
jpayne@68
|
169 private int dumpBuffer_inner(final int way){
|
jpayne@68
|
170 if(verbose){System.err.println("Dumping buffer for way "+way+" of "+ways);}
|
jpayne@68
|
171 final KmerBuffer buffer=buffers[way];
|
jpayne@68
|
172 final int lim=buffer.size();
|
jpayne@68
|
173 if(lim<1){return 0;}
|
jpayne@68
|
174 final long[] kmers=buffer.kmers.array;
|
jpayne@68
|
175 final int[] values=(buffer.values==null ? null : buffer.values.array);
|
jpayne@68
|
176 if(lim<1){return 0;}
|
jpayne@68
|
177 int added=0;
|
jpayne@68
|
178 final AbstractKmerTable table=tables[way];
|
jpayne@68
|
179 // synchronized(table){
|
jpayne@68
|
180 if(values==null){
|
jpayne@68
|
181 // Arrays.sort(kmers, 0, lim); //Makes it slower
|
jpayne@68
|
182 if(SORT_BUFFERS){
|
jpayne@68
|
183 long prev=-1;
|
jpayne@68
|
184 int sum=0;
|
jpayne@68
|
185 for(int i=0; i<lim; i++){
|
jpayne@68
|
186 final long kmer=kmers[i];
|
jpayne@68
|
187 if(kmer==prev){
|
jpayne@68
|
188 sum++;
|
jpayne@68
|
189 }else{
|
jpayne@68
|
190 if(sum>0){added+=table.incrementAndReturnNumCreated(prev, sum);}
|
jpayne@68
|
191 prev=kmer;
|
jpayne@68
|
192 sum=1;
|
jpayne@68
|
193 }
|
jpayne@68
|
194 }
|
jpayne@68
|
195 if(sum>0){added+=table.incrementAndReturnNumCreated(prev, sum);}
|
jpayne@68
|
196 }else{
|
jpayne@68
|
197 for(int i=0; i<lim; i++){
|
jpayne@68
|
198 final long kmer=kmers[i];
|
jpayne@68
|
199 added+=table.incrementAndReturnNumCreated(kmer, 1);
|
jpayne@68
|
200 }
|
jpayne@68
|
201 }
|
jpayne@68
|
202 }else{
|
jpayne@68
|
203 if(setIfNotPresent){
|
jpayne@68
|
204 for(int i=0; i<lim; i++){
|
jpayne@68
|
205 final long kmer=kmers[i];
|
jpayne@68
|
206 final int value=values[i];
|
jpayne@68
|
207 added+=table.setIfNotPresent(kmer, value);
|
jpayne@68
|
208 }
|
jpayne@68
|
209 }else{
|
jpayne@68
|
210 for(int i=0; i<lim; i++){
|
jpayne@68
|
211 final long kmer=kmers[i];
|
jpayne@68
|
212 final int value=values[i];
|
jpayne@68
|
213 added+=table.set(kmer, value);
|
jpayne@68
|
214 // System.err.println("B: "+kmer+", "+Arrays.toString(((HashArrayHybrid)table).getValues(kmer, new int[1])));
|
jpayne@68
|
215 }
|
jpayne@68
|
216 }
|
jpayne@68
|
217 }
|
jpayne@68
|
218 // }
|
jpayne@68
|
219 buffer.clear();
|
jpayne@68
|
220 uniqueAdded+=added;
|
jpayne@68
|
221 return added;
|
jpayne@68
|
222 }
|
jpayne@68
|
223
|
jpayne@68
|
224 /*--------------------------------------------------------------*/
|
jpayne@68
|
225 /*---------------- Resizing and Rebalancing ----------------*/
|
jpayne@68
|
226 /*--------------------------------------------------------------*/
|
jpayne@68
|
227
|
jpayne@68
|
228 @Override
|
jpayne@68
|
229 final boolean canResize() {return false;}
|
jpayne@68
|
230
|
jpayne@68
|
231 @Override
|
jpayne@68
|
232 public final boolean canRebalance() {return false;}
|
jpayne@68
|
233
|
jpayne@68
|
234 @Deprecated
|
jpayne@68
|
235 @Override
|
jpayne@68
|
236 public long size() {
|
jpayne@68
|
237 throw new RuntimeException("Unimplemented.");
|
jpayne@68
|
238 }
|
jpayne@68
|
239
|
jpayne@68
|
240 @Deprecated
|
jpayne@68
|
241 @Override
|
jpayne@68
|
242 public int arrayLength() {
|
jpayne@68
|
243 throw new RuntimeException("Unimplemented.");
|
jpayne@68
|
244 }
|
jpayne@68
|
245
|
jpayne@68
|
246 @Deprecated
|
jpayne@68
|
247 @Override
|
jpayne@68
|
248 void resize() {
|
jpayne@68
|
249 throw new RuntimeException("Unimplemented.");
|
jpayne@68
|
250 }
|
jpayne@68
|
251
|
jpayne@68
|
252 @Deprecated
|
jpayne@68
|
253 @Override
|
jpayne@68
|
254 public void rebalance() {
|
jpayne@68
|
255 throw new RuntimeException("Unimplemented.");
|
jpayne@68
|
256 }
|
jpayne@68
|
257
|
jpayne@68
|
258 @Override
|
jpayne@68
|
259 public long regenerate(final int limit){
|
jpayne@68
|
260 long sum=0;
|
jpayne@68
|
261 for(AbstractKmerTable table : tables){
|
jpayne@68
|
262 sum+=table.regenerate(limit);
|
jpayne@68
|
263 }
|
jpayne@68
|
264 return sum;
|
jpayne@68
|
265 }
|
jpayne@68
|
266
|
jpayne@68
|
267 /*--------------------------------------------------------------*/
|
jpayne@68
|
268 /*---------------- Info Dumping ----------------*/
|
jpayne@68
|
269 /*--------------------------------------------------------------*/
|
jpayne@68
|
270
|
jpayne@68
|
271 @Override
|
jpayne@68
|
272 public boolean dumpKmersAsText(TextStreamWriter tsw, int k, int mincount, int maxcount){
|
jpayne@68
|
273 for(AbstractKmerTable table : tables){
|
jpayne@68
|
274 table.dumpKmersAsText(tsw, k, mincount, maxcount);
|
jpayne@68
|
275 }
|
jpayne@68
|
276 return true;
|
jpayne@68
|
277 }
|
jpayne@68
|
278
|
jpayne@68
|
279 @Override
|
jpayne@68
|
280 public boolean dumpKmersAsBytes(ByteStreamWriter bsw, int k, int mincount, int maxcount, AtomicLong remaining){
|
jpayne@68
|
281 for(AbstractKmerTable table : tables){
|
jpayne@68
|
282 table.dumpKmersAsBytes(bsw, k, mincount, maxcount, remaining);
|
jpayne@68
|
283 }
|
jpayne@68
|
284 return true;
|
jpayne@68
|
285 }
|
jpayne@68
|
286
|
jpayne@68
|
287 @Override
|
jpayne@68
|
288 @Deprecated
|
jpayne@68
|
289 public boolean dumpKmersAsBytes_MT(final ByteStreamWriter bsw, final ByteBuilder bb, final int k, final int mincount, int maxcount, AtomicLong remaining){
|
jpayne@68
|
290 throw new RuntimeException("Unsupported.");
|
jpayne@68
|
291 }
|
jpayne@68
|
292
|
jpayne@68
|
293 @Override
|
jpayne@68
|
294 @Deprecated
|
jpayne@68
|
295 public void fillHistogram(long[] ca, int max){
|
jpayne@68
|
296 throw new RuntimeException("Unsupported.");
|
jpayne@68
|
297 }
|
jpayne@68
|
298
|
jpayne@68
|
299 @Override
|
jpayne@68
|
300 @Deprecated
|
jpayne@68
|
301 public void fillHistogram(SuperLongList sll){
|
jpayne@68
|
302 throw new RuntimeException("Unsupported.");
|
jpayne@68
|
303 }
|
jpayne@68
|
304
|
jpayne@68
|
305 @Override
|
jpayne@68
|
306 public void countGC(long[] gcCounts, int max){
|
jpayne@68
|
307 for(AbstractKmerTable table : tables){
|
jpayne@68
|
308 table.countGC(gcCounts, max);
|
jpayne@68
|
309 }
|
jpayne@68
|
310 }
|
jpayne@68
|
311
|
jpayne@68
|
312 /*--------------------------------------------------------------*/
|
jpayne@68
|
313 /*---------------- Invalid Methods ----------------*/
|
jpayne@68
|
314 /*--------------------------------------------------------------*/
|
jpayne@68
|
315
|
jpayne@68
|
316 @Override
|
jpayne@68
|
317 public int increment(final long kmer, final int incr) {
|
jpayne@68
|
318 throw new RuntimeException("Unsupported");
|
jpayne@68
|
319 }
|
jpayne@68
|
320
|
jpayne@68
|
321 /*--------------------------------------------------------------*/
|
jpayne@68
|
322 /*---------------- Fields ----------------*/
|
jpayne@68
|
323 /*--------------------------------------------------------------*/
|
jpayne@68
|
324
|
jpayne@68
|
325 private final AbstractKmerTable[] tables;
|
jpayne@68
|
326 private final int buflen;
|
jpayne@68
|
327 private final int halflen;
|
jpayne@68
|
328 private final int ways;
|
jpayne@68
|
329 private final boolean useValues;
|
jpayne@68
|
330 private final KmerBuffer[] buffers;
|
jpayne@68
|
331 private final long coreMask;
|
jpayne@68
|
332 public long uniqueAdded=0;
|
jpayne@68
|
333
|
jpayne@68
|
334 private static final int SIZEMASK=15;
|
jpayne@68
|
335 private final boolean setIfNotPresent;
|
jpayne@68
|
336
|
jpayne@68
|
337 public static boolean SORT_BUFFERS=false;
|
jpayne@68
|
338
|
jpayne@68
|
339 }
|