jpayne@68
|
1 package kmer;
|
jpayne@68
|
2
|
jpayne@68
|
3 import java.util.Arrays;
|
jpayne@68
|
4 import java.util.concurrent.atomic.AtomicLong;
|
jpayne@68
|
5
|
jpayne@68
|
6 import fileIO.ByteStreamWriter;
|
jpayne@68
|
7 import shared.KillSwitch;
|
jpayne@68
|
8 import shared.Shared;
|
jpayne@68
|
9 import shared.Tools;
|
jpayne@68
|
10 import structures.ByteBuilder;
|
jpayne@68
|
11
|
jpayne@68
|
12 /**
|
jpayne@68
|
13 * Allows multiple values per kmer.
|
jpayne@68
|
14 * @author Brian Bushnell
|
jpayne@68
|
15 * @date Nov 7, 2014
|
jpayne@68
|
16 *
|
jpayne@68
|
17 */
|
jpayne@68
|
18 public class KmerNode2D extends KmerNode {
|
jpayne@68
|
19
|
jpayne@68
|
20 /*--------------------------------------------------------------*/
|
jpayne@68
|
21 /*---------------- Initialization ----------------*/
|
jpayne@68
|
22 /*--------------------------------------------------------------*/
|
jpayne@68
|
23
|
jpayne@68
|
24 public KmerNode2D(long pivot_){
|
jpayne@68
|
25 super(pivot_);
|
jpayne@68
|
26 }
|
jpayne@68
|
27
|
jpayne@68
|
28 public KmerNode2D(long pivot_, int value_){
|
jpayne@68
|
29 super(pivot_);
|
jpayne@68
|
30 assert(value_>=0 || value_==-1);
|
jpayne@68
|
31 values=new int[] {value_, -1};
|
jpayne@68
|
32 numValues=1;
|
jpayne@68
|
33 }
|
jpayne@68
|
34
|
jpayne@68
|
35 public KmerNode2D(long pivot_, int[] vals_, int vlen){
|
jpayne@68
|
36 super(pivot_);
|
jpayne@68
|
37 values=vals_;
|
jpayne@68
|
38 numValues=vlen;
|
jpayne@68
|
39 assert(values!=null || vlen==0);
|
jpayne@68
|
40 assert(values==null || (vlen<=values.length && vlen>=0));
|
jpayne@68
|
41 // assert(countValues(values)==vlen) : countValues(values)+", "+vlen; //TODO: Slow assertion //123
|
jpayne@68
|
42 }
|
jpayne@68
|
43
|
jpayne@68
|
44 @Override
|
jpayne@68
|
45 public final KmerNode makeNode(long pivot_, int value_){
|
jpayne@68
|
46 return new KmerNode2D(pivot_, value_);
|
jpayne@68
|
47 }
|
jpayne@68
|
48
|
jpayne@68
|
49 @Override
|
jpayne@68
|
50 public final KmerNode makeNode(long pivot_, int[] values_, int vlen){
|
jpayne@68
|
51 return new KmerNode2D(pivot_, values_, vlen);
|
jpayne@68
|
52 }
|
jpayne@68
|
53
|
jpayne@68
|
54 /*--------------------------------------------------------------*/
|
jpayne@68
|
55 /*---------------- Public Methods ----------------*/
|
jpayne@68
|
56 /*--------------------------------------------------------------*/
|
jpayne@68
|
57
|
jpayne@68
|
58 // public final int set_Test(final long kmer, final int v[]){
|
jpayne@68
|
59 // assert(TESTMODE);
|
jpayne@68
|
60 // final int x;
|
jpayne@68
|
61 // if(TWOD()){
|
jpayne@68
|
62 // int[] old=getValues(kmer, null);
|
jpayne@68
|
63 // assert(old==null || contains(kmer, old));
|
jpayne@68
|
64 // x=set0(kmer, v);
|
jpayne@68
|
65 // assert(old==null || contains(kmer, old));
|
jpayne@68
|
66 // assert(contains(kmer, v));
|
jpayne@68
|
67 // }else{
|
jpayne@68
|
68 // int old=getValue(kmer);
|
jpayne@68
|
69 // assert(old==0 || old==-1 || contains(kmer, old));
|
jpayne@68
|
70 // x=set0(kmer, v);
|
jpayne@68
|
71 // assert(contains(kmer, v)) : "old="+old+", v="+v+", kmer="+kmer+", get(kmer)="+getValue(kmer);
|
jpayne@68
|
72 // assert(v[0]==old || !contains(kmer, old));
|
jpayne@68
|
73 // }
|
jpayne@68
|
74 // return x;
|
jpayne@68
|
75 // }
|
jpayne@68
|
76
|
jpayne@68
|
77 /** Returns number of nodes added */
|
jpayne@68
|
78 @Override
|
jpayne@68
|
79 public int set(long kmer, int vals[], int vlen){
|
jpayne@68
|
80 if(pivot<0){pivot=kmer; insertValue(vals, vlen); return 1;} //Allows initializing empty nodes to -1
|
jpayne@68
|
81 if(kmer<pivot){
|
jpayne@68
|
82 if(left==null){left=new KmerNode2D(kmer, vals, vlen); return 1;}
|
jpayne@68
|
83 return left.set(kmer, vals, vlen);
|
jpayne@68
|
84 }else if(kmer>pivot){
|
jpayne@68
|
85 if(right==null){right=new KmerNode2D(kmer, vals, vlen); return 1;}
|
jpayne@68
|
86 return right.set(kmer, vals, vlen);
|
jpayne@68
|
87 }else{
|
jpayne@68
|
88 insertValue(vals, vlen);
|
jpayne@68
|
89 }
|
jpayne@68
|
90 return 0;
|
jpayne@68
|
91 }
|
jpayne@68
|
92
|
jpayne@68
|
93 /*--------------------------------------------------------------*/
|
jpayne@68
|
94 /*---------------- Nonpublic Methods ----------------*/
|
jpayne@68
|
95 /*--------------------------------------------------------------*/
|
jpayne@68
|
96
|
jpayne@68
|
97 @Override
|
jpayne@68
|
98 protected int value(){return values==null ? 0 : values[0];}
|
jpayne@68
|
99
|
jpayne@68
|
100 @Override
|
jpayne@68
|
101 protected int[] values(int[] singleton){
|
jpayne@68
|
102 return values;
|
jpayne@68
|
103 }
|
jpayne@68
|
104
|
jpayne@68
|
105 @Override
|
jpayne@68
|
106 public int set(int value_){
|
jpayne@68
|
107 insertValue(value_);
|
jpayne@68
|
108 return value_;
|
jpayne@68
|
109 }
|
jpayne@68
|
110
|
jpayne@68
|
111 @Override
|
jpayne@68
|
112 protected int set(int[] values_, int vlen){
|
jpayne@68
|
113 int ret=(values==null ? 1 : 0);
|
jpayne@68
|
114 insertValue(values_, vlen);
|
jpayne@68
|
115 return ret;
|
jpayne@68
|
116 }
|
jpayne@68
|
117
|
jpayne@68
|
118 @Override
|
jpayne@68
|
119 int numValues(){
|
jpayne@68
|
120 // assert(countValues(values)==numValues) : countValues(values)+", "+numValues; //TODO: Slow assertion //123
|
jpayne@68
|
121 return numValues;
|
jpayne@68
|
122 // asdf
|
jpayne@68
|
123 // if(values==null){return 0;}
|
jpayne@68
|
124 // for(int i=0; i<values.length; i++){
|
jpayne@68
|
125 // if(values[i]==-1){return i;}
|
jpayne@68
|
126 // }
|
jpayne@68
|
127 // return values.length;
|
jpayne@68
|
128 }
|
jpayne@68
|
129
|
jpayne@68
|
130 /*--------------------------------------------------------------*/
|
jpayne@68
|
131 /*---------------- Private Methods ----------------*/
|
jpayne@68
|
132 /*--------------------------------------------------------------*/
|
jpayne@68
|
133
|
jpayne@68
|
134 /** Returns number of values added */
|
jpayne@68
|
135 private int insertValue(int v){
|
jpayne@68
|
136 return insertIntoList(v);
|
jpayne@68
|
137 }
|
jpayne@68
|
138
|
jpayne@68
|
139 /** Returns number of values added */
|
jpayne@68
|
140 private int insertValue(int[] vals, int vlen){
|
jpayne@68
|
141 // assert(countValues(vals)==vlen) : countValues(vals)+", "+vlen; //TODO: Slow assertion //123
|
jpayne@68
|
142 assert(vals!=null || vlen==0);
|
jpayne@68
|
143 assert(vals==null || (vlen<=vals.length && vlen>=0));
|
jpayne@68
|
144 if(values==null){
|
jpayne@68
|
145 values=vals;
|
jpayne@68
|
146 numValues=vlen;
|
jpayne@68
|
147 return 1;
|
jpayne@68
|
148 }
|
jpayne@68
|
149 for(int v : vals){
|
jpayne@68
|
150 if(v<0){break;}
|
jpayne@68
|
151 insertIntoList(v);
|
jpayne@68
|
152 }
|
jpayne@68
|
153 return 0;
|
jpayne@68
|
154 }
|
jpayne@68
|
155
|
jpayne@68
|
156 private final int countValues(int[] vals){
|
jpayne@68
|
157 if(vals==null) {return 0;}
|
jpayne@68
|
158 int count=0;
|
jpayne@68
|
159 for(int v : vals){
|
jpayne@68
|
160 if(v>=0){
|
jpayne@68
|
161 count++;
|
jpayne@68
|
162 }else{
|
jpayne@68
|
163 break;
|
jpayne@68
|
164 }
|
jpayne@68
|
165 }
|
jpayne@68
|
166 return count;
|
jpayne@68
|
167 }
|
jpayne@68
|
168
|
jpayne@68
|
169 private final int insertIntoList(final int v){
|
jpayne@68
|
170 // assert(countValues(values)==numValues) : countValues(values)+", "+numValues; //TODO: Slow assertion //123
|
jpayne@68
|
171 assert(v>=0);
|
jpayne@68
|
172
|
jpayne@68
|
173 if(values==null){
|
jpayne@68
|
174 values=new int[] {v, -1};
|
jpayne@68
|
175 numValues=1;
|
jpayne@68
|
176 return 1;
|
jpayne@68
|
177 }
|
jpayne@68
|
178
|
jpayne@68
|
179 for(int i=numValues-1, lim=Tools.max(0, numValues-slowAddLimit); i>=lim; i--){//This is the slow bit
|
jpayne@68
|
180 if(values[i]==v){return 0;}
|
jpayne@68
|
181 if(values[i]<0){
|
jpayne@68
|
182 values[i]=v;
|
jpayne@68
|
183 numValues++;
|
jpayne@68
|
184 return 1;
|
jpayne@68
|
185 }
|
jpayne@68
|
186 }
|
jpayne@68
|
187 //At this point the size is big, or the element was not found
|
jpayne@68
|
188
|
jpayne@68
|
189 if(numValues>=values.length){//resize
|
jpayne@68
|
190 assert(numValues==values.length);
|
jpayne@68
|
191 final int oldSize=values.length;
|
jpayne@68
|
192 final int newSize=(int)Tools.min(Shared.MAX_ARRAY_LEN, oldSize*2L);
|
jpayne@68
|
193 assert(newSize>values.length) : "Overflow.";
|
jpayne@68
|
194 values=KillSwitch.copyOf(values, newSize);
|
jpayne@68
|
195 Arrays.fill(values, oldSize, newSize, -1);
|
jpayne@68
|
196 }
|
jpayne@68
|
197
|
jpayne@68
|
198 //quick add
|
jpayne@68
|
199 assert(values[numValues]<0);
|
jpayne@68
|
200 values[numValues]=v;
|
jpayne@68
|
201 numValues++;
|
jpayne@68
|
202
|
jpayne@68
|
203 // assert(countValues(values)==numValues) : countValues(values)+", "+numValues; //TODO: Slow assertion //123
|
jpayne@68
|
204 return 1;
|
jpayne@68
|
205 }
|
jpayne@68
|
206
|
jpayne@68
|
207 /*--------------------------------------------------------------*/
|
jpayne@68
|
208 /*---------------- Resizing and Rebalancing ----------------*/
|
jpayne@68
|
209 /*--------------------------------------------------------------*/
|
jpayne@68
|
210
|
jpayne@68
|
211 @Override
|
jpayne@68
|
212 boolean canResize() {
|
jpayne@68
|
213 return false;
|
jpayne@68
|
214 }
|
jpayne@68
|
215
|
jpayne@68
|
216 @Override
|
jpayne@68
|
217 public boolean canRebalance() {
|
jpayne@68
|
218 return true;
|
jpayne@68
|
219 }
|
jpayne@68
|
220
|
jpayne@68
|
221 @Deprecated
|
jpayne@68
|
222 @Override
|
jpayne@68
|
223 public int arrayLength() {
|
jpayne@68
|
224 throw new RuntimeException("Unsupported.");
|
jpayne@68
|
225 }
|
jpayne@68
|
226
|
jpayne@68
|
227 @Deprecated
|
jpayne@68
|
228 @Override
|
jpayne@68
|
229 void resize() {
|
jpayne@68
|
230 throw new RuntimeException("Unsupported.");
|
jpayne@68
|
231 }
|
jpayne@68
|
232
|
jpayne@68
|
233 @Deprecated
|
jpayne@68
|
234 @Override
|
jpayne@68
|
235 public void rebalance() {
|
jpayne@68
|
236 throw new RuntimeException("Please call rebalance(ArrayList<KmerNode>) instead, with an empty list.");
|
jpayne@68
|
237 }
|
jpayne@68
|
238
|
jpayne@68
|
239 /*--------------------------------------------------------------*/
|
jpayne@68
|
240 /*---------------- Info Dumping ----------------*/
|
jpayne@68
|
241 /*--------------------------------------------------------------*/
|
jpayne@68
|
242
|
jpayne@68
|
243 @Override
|
jpayne@68
|
244 public final boolean dumpKmersAsBytes(ByteStreamWriter bsw, int k, int mincount, int maxcount, AtomicLong remaining){
|
jpayne@68
|
245 if(values==null){return true;}
|
jpayne@68
|
246 if(remaining!=null && remaining.decrementAndGet()<0){return true;}
|
jpayne@68
|
247 bsw.printlnKmer(pivot, values, k);
|
jpayne@68
|
248 if(left!=null){left.dumpKmersAsBytes(bsw, k, mincount, maxcount, remaining);}
|
jpayne@68
|
249 if(right!=null){right.dumpKmersAsBytes(bsw, k, mincount, maxcount, remaining);}
|
jpayne@68
|
250 return true;
|
jpayne@68
|
251 }
|
jpayne@68
|
252
|
jpayne@68
|
253 @Override
|
jpayne@68
|
254 public final boolean dumpKmersAsBytes_MT(final ByteStreamWriter bsw, final ByteBuilder bb, final int k, final int mincount, int maxcount, AtomicLong remaining){
|
jpayne@68
|
255 if(values==null){return true;}
|
jpayne@68
|
256 if(remaining!=null && remaining.decrementAndGet()<0){return true;}
|
jpayne@68
|
257 toBytes(pivot, values, k, bb);
|
jpayne@68
|
258 bb.nl();
|
jpayne@68
|
259 if(bb.length()>=16000){
|
jpayne@68
|
260 ByteBuilder bb2=new ByteBuilder(bb);
|
jpayne@68
|
261 synchronized(bsw){bsw.addJob(bb2);}
|
jpayne@68
|
262 bb.clear();
|
jpayne@68
|
263 }
|
jpayne@68
|
264 if(left!=null){left.dumpKmersAsBytes_MT(bsw, bb, k, mincount, maxcount, remaining);}
|
jpayne@68
|
265 if(right!=null){right.dumpKmersAsBytes_MT(bsw, bb, k, mincount, maxcount, remaining);}
|
jpayne@68
|
266 return true;
|
jpayne@68
|
267 }
|
jpayne@68
|
268
|
jpayne@68
|
269 @Override
|
jpayne@68
|
270 protected final StringBuilder dumpKmersAsText(StringBuilder sb, int k, int mincount, int maxcount){
|
jpayne@68
|
271 if(values==null){return sb;}
|
jpayne@68
|
272 if(sb==null){sb=new StringBuilder(32);}
|
jpayne@68
|
273 sb.append(AbstractKmerTable.toText(pivot, values, k)).append('\n');
|
jpayne@68
|
274 if(left!=null){left.dumpKmersAsText(sb, k, mincount, maxcount);}
|
jpayne@68
|
275 if(right!=null){right.dumpKmersAsText(sb, k, mincount, maxcount);}
|
jpayne@68
|
276 return sb;
|
jpayne@68
|
277 }
|
jpayne@68
|
278
|
jpayne@68
|
279 @Override
|
jpayne@68
|
280 protected final ByteBuilder dumpKmersAsText(ByteBuilder bb, int k, int mincount, int maxcount){
|
jpayne@68
|
281 if(values==null){return bb;}
|
jpayne@68
|
282 if(bb==null){bb=new ByteBuilder(32);}
|
jpayne@68
|
283 bb.append(AbstractKmerTable.toBytes(pivot, values, k)).append('\n');
|
jpayne@68
|
284 if(left!=null){left.dumpKmersAsText(bb, k, mincount, maxcount);}
|
jpayne@68
|
285 if(right!=null){right.dumpKmersAsText(bb, k, mincount, maxcount);}
|
jpayne@68
|
286 return bb;
|
jpayne@68
|
287 }
|
jpayne@68
|
288
|
jpayne@68
|
289 @Override
|
jpayne@68
|
290 final boolean TWOD(){return true;}
|
jpayne@68
|
291
|
jpayne@68
|
292 /*--------------------------------------------------------------*/
|
jpayne@68
|
293 /*---------------- Invalid Methods ----------------*/
|
jpayne@68
|
294 /*--------------------------------------------------------------*/
|
jpayne@68
|
295
|
jpayne@68
|
296 /*--------------------------------------------------------------*/
|
jpayne@68
|
297 /*---------------- Fields ----------------*/
|
jpayne@68
|
298 /*--------------------------------------------------------------*/
|
jpayne@68
|
299
|
jpayne@68
|
300 int[] values;
|
jpayne@68
|
301 private int numValues;
|
jpayne@68
|
302 private static final int slowAddLimit=4;
|
jpayne@68
|
303
|
jpayne@68
|
304 }
|