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