1 package var; 2 import java.io.Serializable; 3 import java.lang.reflect.Array; 4 import java.util.ArrayList; 5 import java.util.Arrays; 6 import java.util.HashMap; 7 import java.util.HashSet; 8 import java.util.Set; 9 10 import dna.Data; 11 import dna.Gene; 12 import dna.GeneSet; 13 import driver.Search; 14 import shared.Shared; 15 import shared.Tools; 16 import structures.Range; 17 18 19 20 public class Variation implements Comparable<Variation>, Serializable, Cloneable { 21 22 // >locus ploidy haplotype chromosome begin end varType reference alleleSeq totalScore hapLink xRef 23 24 /** 25 * 26 */ 27 private static final long serialVersionUID = -3847258470952802740l; 28 Variation(VarLine line)29 public Variation(VarLine line){ 30 // this(line.chromosome, line.beginLoc, line.endLoc, line.xRef, line.varType, line.ref, line.call); 31 this(line.chromosome, line.beginLoc, line.endLoc, line.varType, line.ref, line.call); 32 33 assert(!((varType==INS || varType==DELINS || varType==SNP) && call==null)) : "\n"+line+"\n"+this+ 34 "\nline.ref="+line.ref+"\nline.call="+line.call+"\nref="+ref+"\ncall="+call; 35 36 assert(beginLoc<=endLoc) : line.toString(); 37 38 assert(this.equals(line)) : "\n\n"+this+"\n!=\n"+line; 39 assert(line.equals(this)) : "\n\n"+this+"\n!=\n"+line; 40 41 42 // if(xRef==11429487){ 43 // System.out.println("\n"+this.toString()); 44 // } 45 } 46 47 // public Variation(GeneVarLine line){ 48 //// this(line.chromosome, line.beginLoc, line.endLoc, line.xRef, line.varType, line.ref, line.call); 49 // this(line.chromosome, line.beginLoc, line.endLoc, line.xRef, line.xRefArray, line.varType, line.ref, line.call); 50 // 51 // assert(beginLoc<=endLoc) : line.toString(); 52 // 53 // assert(this.equals(line)) : "\n\n"+this+"\n!=\n"+line.toSuperString()+"\n\n"+line; 54 // assert(line.equals(this)) : "\n\n"+this+"\n!=\n"+line.toSuperString()+"\n\n"+line; 55 // 56 // } 57 Variation(Variation line)58 public Variation(Variation line){ 59 this(line.chromosome, line.beginLoc, line.endLoc, line.varType, line.ref, line.call); 60 61 assert(beginLoc<=endLoc) : line.toString(); 62 63 assert(this.equals(line)) : "\n\n"+this+"\n!=\n"+line.toSuperString()+"\n\n"+line; 64 assert(line.equals(this)) : "\n\n"+this+"\n!=\n"+line.toSuperString()+"\n\n"+line; 65 66 } 67 Variation(int chr, int bLoc, int eLoc, byte vType, String rf, String ca)68 public Variation(int chr, int bLoc, int eLoc, byte vType, String rf, String ca){ 69 chromosome=chr; 70 beginLoc=bLoc; 71 endLoc=eLoc; 72 varType=vType; 73 74 setDetails(vType, rf, ca); 75 76 assert(beginLoc<=endLoc) : toString(); 77 78 } 79 Variation()80 public Variation(){} 81 82 83 @Override clone()84 public Variation clone(){ 85 Variation v=null; 86 try { 87 v=(Variation) super.clone(); 88 } catch (CloneNotSupportedException e) { 89 // TODO Auto-generated catch block 90 e.printStackTrace(); 91 } 92 return v; 93 } 94 95 toVariations(VarLine[] array, boolean retainEqual)96 public static final HashSet<Variation> toVariations(VarLine[] array, boolean retainEqual){ 97 HashSet<Variation> set=new HashSet<Variation>(array.length); 98 for(VarLine line : array){ 99 Variation var=new Variation(line); 100 if(retainEqual || var.varType!=Variation.REF){ 101 if(!set.contains(var)){ 102 set.add(var); 103 } 104 } 105 } 106 return set; 107 } 108 toVariationArray(VarLine[][] array, boolean retainEqual)109 public static final Variation[] toVariationArray(VarLine[][] array, boolean retainEqual){ 110 HashSet<Variation> set=toVariations(array[0], retainEqual); 111 for(int i=1; i<array.length; i++){ 112 set.addAll(toVariations(array[i], retainEqual)); 113 } 114 Variation[] vars=set.toArray(new Variation[set.size()]); 115 Arrays.sort(vars); 116 return vars; 117 } 118 toVariationArray(VarLine[] array, boolean retainEqual)119 public static final Variation[] toVariationArray(VarLine[] array, boolean retainEqual){ 120 HashSet<Variation> set=toVariations(array, retainEqual); 121 Variation[] vars=set.toArray(new Variation[set.size()]); 122 Arrays.sort(vars); 123 return vars; 124 } 125 126 @SuppressWarnings("unchecked") toArray(Class<X> c, Set<X> set)127 public static final <X extends Comparable<? super X>> X[] toArray(Class<X> c, Set<X> set){ 128 129 set.getClass().getTypeParameters(); 130 X[] array=(X[])Array.newInstance(c,set.size()); 131 132 array=set.toArray(array); 133 int i=0; 134 for(X x : set){ 135 array[i]=x; 136 i++; 137 } 138 Arrays.sort(array); 139 return array; 140 } 141 142 filterCodingVariances(VarLine[] variances, int chrom, boolean nearby)143 public static VarLine[] filterCodingVariances(VarLine[] variances, int chrom, boolean nearby){ 144 Range[] ranges=(nearby ? Data.geneNearbyRangeMatrix(chrom) : Data.geneCodeAndExonRangeMatrix(chrom)); 145 146 ArrayList<VarLine> list=new ArrayList<VarLine>(8+variances.length/8); 147 148 for(VarLine var : variances){ 149 150 if(var.varType!=VarLine.REF && var.varType!=VarLine.NOREF){ 151 int loc=var.beginLoc; 152 int rnum=Search.findPointBinary(loc, ranges); 153 154 if(ranges[rnum].intersects(var.beginLoc, var.endLoc)){ 155 list.add(var); 156 } 157 158 for(int i=rnum; i<ranges.length; i++){ 159 Range r=ranges[i]; 160 if(r.a>var.endLoc){break;} //Out of range 161 162 if(r.intersects(var.beginLoc, var.endLoc)){ 163 list.add(var); 164 break; 165 } 166 } 167 } 168 } 169 170 return list.toArray(new VarLine[list.size()]); 171 } 172 173 174 175 176 /** 177 * Generates an array of non-overlapping Ranges, sorted by index, ascending. 178 * To each is attached a list of all overlapping Variations from the input array. 179 * @param va 180 * @return The array of ranges 181 */ makeVarRanges(Variation[] va)182 public static Range[] makeVarRanges(Variation[] va){ 183 // System.out.println("va.length="+va.length); 184 185 if(va==null || va.length==0){ 186 return new Range[0]; 187 } 188 189 ArrayList<Range> ra=new ArrayList<Range>(va.length); 190 for(Variation v : va){ 191 Range r=new Range(v.beginLoc, v.endLoc); 192 r.obj1=new ArrayList<Variation>(); 193 ((ArrayList<Variation>)r.obj1).add(v); 194 ra.add(r); 195 } 196 Shared.sort(ra); 197 ArrayList<Range> ra2=new ArrayList<Range>(va.length); 198 Range current=null; 199 // System.out.println("ra.size="+ra.size()); 200 for(Range r : ra){ 201 // System.out.println("\ncurrent="+current+", r="+r); 202 if(current==null){current=r;} 203 else if(current.intersects(r)){ 204 // System.out.println("merged"); 205 Range temp=current.merge(r); 206 temp.obj1=current.obj1; 207 ((ArrayList<Variation>)temp.obj1).addAll((ArrayList<Variation>)r.obj1); 208 current=temp; 209 }else{ 210 // System.out.println("added"); 211 ra2.add(current); 212 current=r; 213 } 214 // System.out.println("current="+current+", r="+r); 215 } 216 // System.out.println("\ncurrent="+current); 217 // System.out.println("ra2.size="+ra2.size()); 218 assert(current!=null); //Note: this could be null if input was empty, I guess... 219 assert(ra2.size()==0 || ra2.get(ra2.size()-1)!=current); 220 ra2.add(current); 221 return ra2.toArray(new Range[ra2.size()]); 222 } 223 toRsid(String s)224 public static final int toRsid(String s){return xRefToId(s);} xRefToId(String s)225 public static final int xRefToId(String s){ 226 // System.out.println(s); 227 if(s==null || s.length()==0){return -1;} 228 // assert(s.startsWith("dbsnp:rs")) : s; 229 230 if(s.contains(":")){ 231 s=s.substring(s.indexOf(':')+1); 232 } 233 234 int i=0, max=s.length(); 235 // System.err.println(s); 236 while(i<max && !Tools.isDigit(s.charAt(i))){i++;} 237 if(i>=max){assert(s.equals(".")) : s; return -1;} 238 s=s.substring(i); 239 240 return Integer.parseInt(s); 241 } 242 toRsidArray(String s)243 public static final int[] toRsidArray(String s){return xRefToIdArray(s);} xRefToIdArray(String s)244 public static final int[] xRefToIdArray(String s){ 245 if(s==null || s.length()<1){return null;} 246 String[] array=s.split("[,;]"); 247 int[] r=new int[array.length]; 248 for(int i=0; i<array.length; i++){ 249 r[i]=xRefToId(array[i]); 250 if(r[i]==-1){ 251 if(r.length==1){return null;} 252 253 //This can be safely disabled. But it is best to fix this case by making the array smaller. 254 assert(false) : "Not a real rsID: "+s; 255 } 256 } 257 return r; 258 } 259 matches(Variation line)260 public boolean matches(Variation line){ 261 if(line==null || chromosome!=line.chromosome || beginLoc!=line.beginLoc || endLoc!=line.endLoc || varType!=line.varType){ 262 return false; 263 } 264 return matches(line.varType, line.ref, line.call); 265 } 266 267 // public boolean matchesLoose(VarLine line){ 268 // if(line==null || chromosome!=line.chromosome || !intersects(line)){ 269 // return false; 270 // } 271 // if(isEqual() && line.isEqual()){return true;} 272 // if(varType!=line.varType){return false;} 273 // return matches(line.varType, line.ref, line.call); 274 // } 275 276 /** Overlap and don't contradict each other */ matchesLoose(VarLine line)277 public boolean matchesLoose(VarLine line){ 278 if(line==null || chromosome!=line.chromosome || !intersects(line)){ 279 return false; 280 } 281 282 if(isTrueVariation()){ 283 if(varType!=line.varType){return false;} 284 return matches(line.varType, line.ref, line.call); 285 }else if(isRef()){ 286 return line.isRef(); 287 }else{ 288 assert(isUnsureVariation()) : this; 289 return line.isUnsureVariation(); 290 } 291 } 292 matches(int type, String ref2, String call2)293 private boolean matches(int type, String ref2, String call2){ 294 if(type==REF || type==REFPOINT || type==DEL || type==NOCALL){ 295 return true; 296 } 297 return call.equals(call2); 298 299 } 300 setDetails(byte vt, String rf, String ca)301 private void setDetails(byte vt, String rf, String ca){ 302 303 ref=null; 304 call=null; 305 306 switch(vt){ 307 308 case REF: { 309 }break; 310 case SNP: { 311 ref=rf; call=ca; 312 }break; 313 case INS: { 314 call=ca; 315 }break; 316 case DEL: { 317 ref=rf; 318 }break; 319 case DELINS: { 320 ref=rf; call=ca; 321 }break; 322 case REFCON: { 323 ref=rf; call=ca; 324 }break; 325 case REFINCON: { 326 ref=rf; call=ca; 327 }break; 328 case NOCALL: { 329 //I can't remember if nocalls need N or null calls 330 // ref=rf; 331 // call=ca; 332 // assert(ref!=null && call!=null && ref.length()==call.length()) : ref+", "+call; 333 }break; 334 case NOREF: { 335 //I can't remember if norefs need N or null refs 336 // ref=rf; 337 call=ca; 338 // assert(ref!=null && call!=null && ref.length()==call.length()) : ref+", "+call; 339 }break; 340 case PAR: { 341 ref=rf; call=ca; 342 }break; 343 case NULL: { 344 ref=rf; call=ca; 345 }break; 346 case REFPOINT: { 347 ref=call=null; 348 }break; 349 350 default: {assert(false);} 351 } 352 intern(); 353 } 354 locationString()355 public String locationString(){ 356 return locationString(0); 357 } 358 locationString(int base)359 public String locationString(int base){ 360 assert(base==0 || base==1); 361 362 if(beginLoc==endLoc){ 363 return "("+(beginLoc+base)+")"; 364 } 365 return "("+(beginLoc+base)+" - "+(endLoc+base)+")"; 366 367 // if(beginLoc==endLoc){ 368 // return (beginLoc+base)+""; 369 // } 370 // return (beginLoc+base)+"-"+(endLoc+base); 371 } 372 toSuperString()373 public String toSuperString(){return toString();} 374 375 @Override toString()376 public String toString(){ 377 return toString(0); 378 } 379 toString(int base)380 public String toString(int base){ 381 StringBuilder sb=new StringBuilder(); 382 383 sb.append("chr"+Gene.chromCodes[chromosome]); 384 while(sb.length()<5){sb.append(' ');} 385 sb.append('\t'); 386 sb.append(locationString(base)+"\t"); 387 388 sb.append(varTypeMap[varType]); 389 390 sb.append("\t"+(ref==null ? "" : ref)); 391 sb.append("\t"+(call==null ? "" : call)); 392 393 sb.append('\t'); 394 395 return sb.toString(); 396 } 397 toSourceString()398 public String toSourceString(){ 399 StringBuilder sb=new StringBuilder(64); 400 401 sb.append("chr"+Gene.chromCodes[chromosome]+"\t"); 402 sb.append(beginLoc+"\t"); 403 404 if(varType==INS){ 405 sb.append(beginLoc+"\t"); 406 }else{ 407 sb.append((endLoc+1)+"\t"); 408 } 409 410 sb.append(varTypeMap[varType]+"\t"); 411 sb.append((ref==null ? "" : ref)+"\t"); 412 sb.append((call==null ? "" : call)+"\t"); 413 414 return sb.toString(); 415 } 416 header()417 public static String header(){ 418 419 return "chrom\tstart\tstop\ttype\tref\tcall\trsID"; 420 } 421 toShortString()422 public String toShortString(){ 423 StringBuilder sb=new StringBuilder(); 424 425 sb.append(locationString()+"\t"); 426 427 sb.append(varTypeMap[varType]); 428 429 if(ref!=null){sb.append("\t"+ref);} 430 if(call!=null){sb.append("\t"+call);} 431 432 return sb.toString(); 433 } 434 435 find(String a, String[] array)436 public static final int find(String a, String[] array){ 437 for(int i=0; i<array.length; i++){ 438 if(a.equals(array[i])){return i;} 439 } 440 assert(false) : "Can't find "+a+" in "+Arrays.toString(array); 441 return -1; 442 } 443 lengthRef()444 public final int lengthRef(){ 445 switch(varType){ 446 case SNP: { 447 assert(endLoc-beginLoc+1==1) : "\n"+endLoc+"-"+beginLoc+"+1 = "+(endLoc-beginLoc+1)+" != "+1+"\n"+this.toString()+"\n"; 448 assert(call!=null && call.length()==1) : "\ncall= '"+call+"'\n"+this.toString(); 449 return 1; 450 } 451 case INS: { 452 return 0; 453 } 454 case REFPOINT: { 455 return 0; 456 } 457 // case NOREF: { 458 // throw new RuntimeException(); 459 // } 460 // case NULL: { 461 // throw new RuntimeException(); 462 // } 463 default: { 464 break; 465 } 466 } 467 return endLoc-beginLoc+1; 468 } 469 lengthMax()470 public final int lengthMax(){return max(lengthRef(), lengthVar());} lengthMin()471 public final int lengthMin(){return min(lengthRef(), lengthVar());} lengthDif()472 public final int lengthDif(){return isNR_or_NC() ? 0 : lengthVar()-lengthRef();} 473 lengthVar()474 public final int lengthVar(){ 475 switch(varType){ 476 477 case REF: { 478 return endLoc-beginLoc+1; 479 } 480 case SNP: { 481 assert(endLoc-beginLoc+1==1); 482 assert(call!=null && call.length()==1); 483 return 1; 484 } 485 case INS: { 486 assert(call!=null); 487 return call.length(); 488 } 489 case REFPOINT: { 490 return 0; 491 } 492 case DEL: { 493 assert(call==null); 494 return 0; 495 } 496 case DELINS: { 497 assert(call!=null); 498 return call.length(); 499 } 500 case REFCON: { 501 return endLoc-beginLoc+1; 502 } 503 case REFINCON: { 504 assert(false) : "Warning - Length cannot be known for certain."; 505 return endLoc-beginLoc+1; 506 } 507 case NOCALL: { 508 assert(false) : "Warning - Length cannot be known for certain."; 509 return endLoc-beginLoc+1; 510 } 511 case NOREF: { 512 assert(false) : "Warning - Length cannot be known for certain."; 513 return endLoc-beginLoc+1; 514 } 515 case PAR: { 516 assert(call!=null); 517 return call.length(); 518 } 519 case NULL: { 520 assert(false); 521 throw new RuntimeException(); 522 } 523 524 default: {throw new RuntimeException();} 525 } 526 } 527 528 529 // //TODO Note that this may be wrong for e.g. insertions, deletions, and if/when changed to half-open numbering. 530 // public final int length(){ 531 // if(varType==INS){return 0;} 532 // return endLoc-beginLoc+1; 533 // } 534 // public final int length2(){ 535 // if(varType==INS){return call==null ? 0 : call.length();} 536 // if(varType==DELINS){return call==null ? (endLoc-beginLoc+1) : max(call.length(), endLoc-beginLoc+1);} 537 // return endLoc-beginLoc+1; 538 // } 539 isPoint()540 public final boolean isPoint(){ 541 return varType==INS || varType==REFPOINT; 542 } 543 isRef()544 public final boolean isRef(){ 545 return varType==REF || varType==REFPOINT; 546 } 547 isTrueVariation()548 public final boolean isTrueVariation(){ 549 return varType==SNP || varType==INS || varType==DEL || varType==DELINS; 550 } 551 isNoCall()552 public final boolean isNoCall(){ 553 return varType==NOCALL || varType==REFCON || varType==REFINCON; 554 } 555 isNR_or_NC()556 public final boolean isNR_or_NC(){ 557 return varType==NOCALL || varType==NOREF || varType==REFCON || varType==REFINCON; 558 } 559 isUnsureVariation()560 public final boolean isUnsureVariation(){ 561 return varType==NOCALL || varType==NOREF || varType==REFINCON || varType==REFCON; 562 } 563 564 565 // /** TODO May be slow. Perhaps add a boolean field. */ 566 // public boolean isCoding(){ 567 // int middle=((beginLoc+endLoc)/2); 568 // GeneSet[] sets=Data.getNearestGeneSets(chromosome, middle); 569 // for(GeneSet gs : sets){ 570 // for(Gene g : gs.genes){ 571 // if(g.intersectsCodeAndExon(beginLoc, endLoc)){ 572 // return true; 573 // } 574 // } 575 // } 576 // return false; 577 // } 578 579 580 /** Does this variation intersect within (range) of a coding region or splice site? */ isNearCodingOrSplice(int range, boolean includeExonsForUntranslatedGenes, boolean includeSplice)581 public boolean isNearCodingOrSplice(int range, boolean includeExonsForUntranslatedGenes, boolean includeSplice){ 582 assert(beginLoc<=endLoc); 583 int a=beginLoc-range, b=endLoc+range; 584 return isNearCodingOrSplice(range, includeExonsForUntranslatedGenes, Data.getNearestGeneSets(chromosome, a, b), includeSplice); 585 } 586 587 588 /** Does this variation intersect within (range) of a coding region or splice site? */ isNearCodingOrSplice(int range, boolean includeExonsForUntranslatedGenes)589 public boolean isNearCodingOrSplice(int range, boolean includeExonsForUntranslatedGenes){ 590 return isNearCodingOrSplice(range, includeExonsForUntranslatedGenes, true); 591 } 592 593 594 /** Does this variation lie at least partially within an intron? */ intersectsIntron()595 public boolean intersectsIntron(){ 596 assert(beginLoc<=endLoc); 597 int a=beginLoc, b=endLoc; 598 return intersectsIntron(Data.getNearestGeneSets(chromosome, a, b)); 599 } 600 601 602 /** Does this variation intersect within (range) of a coding region or splice site? */ isNearCodingOrSplice(int range, boolean includeExonsForUntranslatedGenes, GeneSet[] sets, boolean includeSplice)603 public boolean isNearCodingOrSplice(int range, boolean includeExonsForUntranslatedGenes, GeneSet[] sets, boolean includeSplice){ 604 assert(beginLoc<=endLoc); 605 int a=beginLoc-range, b=endLoc+range; 606 607 // int middle=((beginLoc+endLoc)/2); 608 // GeneSet[] sets=Data.getNearestGeneSets(chromosome, middle); 609 610 // boolean flag=(chromosome==21 && intersects(9929078));//TODO UNDO 611 612 // if(flag){System.out.println("Found: "+Arrays.toString(sets));} 613 // assert(false); 614 615 if(sets==null){ 616 assert(chromosome>=25); 617 return true; 618 } 619 620 621 for(GeneSet gs : sets){ 622 // if(flag){System.out.println("### "+gs);}//TODO UNDO 623 for(Gene g : gs.genes){ 624 625 if(!g.untranslated){ 626 627 // if(flag){System.out.println("*** "+g);}//TODO UNDO 628 629 // if(flag){ 630 // System.out.println("intersectsCodeAndExon: "+g.intersectsCodeAndExon(a, b)); 631 // System.out.println("intersectsCode: "+g.intersectsCode(a, b)); 632 // System.out.println("intersectsExon: "+g.intersectsExon(a, b)); 633 // } 634 635 if(g.intersectsCodeAndExon(a, b)){ 636 return true; 637 } 638 639 }else if(includeExonsForUntranslatedGenes){ 640 // if(flag){System.out.println("*** "+g);}//TODO UNDO 641 // 642 // if(flag){ 643 // System.out.println("intersectsExon: "+g.intersectsExon(a, b)); 644 // } 645 646 if(g.intersectsExon(a, b)){ 647 return true; 648 } 649 650 } 651 652 if(includeSplice){ 653 int[] array=g.nearestSpliceSite(beginLoc, endLoc); 654 if(array[0]<=range){return true;} 655 } 656 657 } 658 } 659 return false; 660 } 661 662 663 /** Does this variation lie at least partially within an intron? */ intersectsIntron(GeneSet[] sets)664 public boolean intersectsIntron(GeneSet[] sets){ 665 assert(beginLoc<=endLoc); 666 int a=beginLoc, b=endLoc; 667 668 // int middle=((beginLoc+endLoc)/2); 669 // GeneSet[] sets=Data.getNearestGeneSets(chromosome, middle); 670 671 if(sets==null){ 672 assert(chromosome>=25); 673 return true; 674 } 675 676 677 for(GeneSet gs : sets){ 678 for(Gene g : gs.genes){ 679 if(g.intersectsIntron(a, b)){return true;} 680 } 681 } 682 return false; 683 } 684 685 public int beginLoc=-2; 686 public int endLoc=-2; 687 688 public int chromosome=-1; 689 public byte varType=-1; 690 691 public String ref=null; 692 public String call=null; 693 694 695 public static final HashMap<Object, Object> ploidyMap=makePloidyMap(); 696 public static final String[] haploMap={"0","1","2","all"}; 697 698 public static final String[] varTypeMap={"ref","snp","ins","del","sub", 699 "no-call-rc","no-call-ri","no-call","no-ref","PAR-called-in-X","null","refpoint"}; 700 701 public static final HashMap<String, Byte> varTypeMap2=makeVarTypeMap(); 702 makeVarTypeMap()703 private static final HashMap<String, Byte> makeVarTypeMap(){ 704 HashMap<String, Byte> r=new HashMap<String, Byte>(32); 705 706 for(byte i=0; i<varTypeMap.length; i++){r.put(varTypeMap[i], i);} 707 r.put("=", REF); 708 r.put("ref-consistent", REFCON); 709 r.put("ref-inconsistent", REFINCON); 710 // r.put("no-call-rc", REFCON); 711 // r.put("no-call-ri", REFINCON); 712 r.put("delins", DELINS); 713 714 return r; 715 } 716 717 public static final byte REF=0; 718 public static final byte SNP=1; 719 public static final byte INS=2; 720 public static final byte DEL=3; 721 public static final byte DELINS=4; 722 public static final byte REFCON=5; 723 public static final byte REFINCON=6; 724 public static final byte NOCALL=7; 725 public static final byte NOREF=8; 726 public static final byte PAR=9; 727 public static final byte NULL=10; 728 public static final byte REFPOINT=11; 729 intern()730 public void intern(){ 731 // assert(false) : ref+", "+call+", "+this; 732 if(ref!=null){ref=Data.intern(ref);} 733 if(call!=null){call=Data.intern(call);} 734 } 735 makePloidyMap()736 private static HashMap<Object, Object> makePloidyMap(){ 737 HashMap<Object, Object> hashy=new HashMap<Object, Object>(64); 738 for(int i=0; i<10; i++){ 739 hashy.put((Byte)(byte)i, i+""); 740 hashy.put((Integer)i, i+""); 741 hashy.put(i+"", (Byte)(byte)i); 742 } 743 hashy.put((Byte)(byte)-1, "?"); 744 hashy.put((Integer)(-1), "?"); 745 hashy.put("?",(Byte)(byte)-1); 746 return hashy; 747 } 748 min(int x, int y)749 private static final int min(int x, int y){return x<y ? x : y;} max(int x, int y)750 private static final int max(int x, int y){return x>y ? x : y;} 751 752 @Override hashCode()753 public final int hashCode(){ 754 long x=chromosome; 755 x=x<<4; 756 x^=varType; 757 x=x<<28; 758 x^=beginLoc; 759 x=x<<16; 760 x^=(endLoc-beginLoc+1); 761 return new Long(x).hashCode(); //TODO: Slow 762 } 763 764 @Override compareTo(Variation other)765 public int compareTo(Variation other) { 766 if(chromosome!=other.chromosome){return other.chromosome>chromosome ? -1 : 1;} 767 if(beginLoc!=other.beginLoc){return other.beginLoc>beginLoc ? -1 : 1;} 768 if(endLoc!=other.endLoc){return other.endLoc>endLoc ? -1 : 1;} 769 if(varType!=other.varType){return other.varType>varType ? -1 : 1;} 770 if(varType==REF || varType==NOCALL){return 0;} 771 772 if(call==null){ 773 return other.call==null ? 0 : -1; 774 } 775 return other.call==null ? 1 : call.compareTo(other.call); 776 } 777 778 @Override equals(Object other)779 public boolean equals(Object other){ 780 return equals((Variation)other); 781 } 782 equals(Variation other)783 public boolean equals(Variation other){ 784 return compareTo(other)==0; 785 } 786 intersects(int point)787 public boolean intersects(int point){ 788 return point>=beginLoc && point<=endLoc; 789 } 790 touches(int point)791 public boolean touches(int point){ 792 return point>=beginLoc-1 && point<=endLoc+1; 793 } 794 795 /** This is quite clever. */ overlap(int a1, int b1, int a2, int b2)796 public static boolean overlap(int a1, int b1, int a2, int b2){ 797 assert(a1<=b1 && a2<=b2) : a1+", "+b1+", "+a2+", "+b2; 798 return a2<=b1 && b2>=a1; 799 } touch(int a1, int b1, int a2, int b2)800 public static boolean touch(int a1, int b1, int a2, int b2){ 801 assert(a1<=b1 && a2<=b2) : a1+", "+b1+", "+a2+", "+b2; 802 return a2<=(b1+1) && b2>=(a1-1); 803 } 804 805 /** Is (a1, b1) within (a2, b2) ? */ isWithin(int a1, int b1, int a2, int b2)806 public static boolean isWithin(int a1, int b1, int a2, int b2){ 807 assert(a1<=b1 && a2<=b2) : a1+", "+b1+", "+a2+", "+b2; 808 return a1>=a2 && b1<=b2; 809 } 810 isWithinNotTouching(int a1, int b1, int a2, int b2)811 public static boolean isWithinNotTouching(int a1, int b1, int a2, int b2){ 812 assert(a1<=b1 && a2<=b2) : a1+", "+b1+", "+a2+", "+b2; 813 return a1>a2 && b1<b2; 814 } 815 816 //Slow if not inlined intersects(int a2, int b2)817 public boolean intersects(int a2, int b2){return overlap(beginLoc, endLoc, a2, b2);} 818 isWithin(int a2, int b2)819 public boolean isWithin(int a2, int b2){return isWithin(beginLoc, endLoc, a2, b2);} 820 isWithinNotTouching(int a2, int b2)821 public boolean isWithinNotTouching(int a2, int b2){return isWithinNotTouching(beginLoc, endLoc, a2, b2);} 822 intersects(Variation v)823 public boolean intersects(Variation v){ 824 825 if(v.chromosome!=chromosome){ 826 return false; 827 } 828 829 int len1=lengthRef(); 830 int len2=v.lengthRef(); 831 832 if(len1<len2){ 833 return v.intersects(this); 834 } 835 836 // if(v.beginLoc==46397336 || v.beginLoc==46397348){ 837 // System.err.println(len1+": "+this+"\n"+len2+": "+v+"\n"); 838 // } 839 //Now, this is at least as long (ref-wise) as v. 840 841 // if(varType==EQUAL && v.varType==INS){ 842 // assert(false); 843 // } 844 845 if(!touch(beginLoc, endLoc, v.beginLoc, v.endLoc)){return false;} 846 847 // if(v.beginLoc==46397336 || v.beginLoc==46397348){ 848 // System.err.println("Touch("+beginLoc+", "+endLoc+", "+v.beginLoc+", "+v.endLoc+")"); 849 // } 850 851 if(v.isPoint()){ 852 // if(v.beginLoc==46397336 || v.beginLoc==46397348){System.out.println("v");} 853 if(isPoint()){ 854 // assert(beginLoc==v.beginLoc && endLoc==v.endLoc) : this+"\n"+v; 855 // return true; 856 857 return beginLoc==v.beginLoc; 858 } 859 // if(v.beginLoc==46397336 || v.beginLoc==46397348){System.out.println("w");} 860 if(this.isNoCall()){ 861 if(len1>0){return overlap(beginLoc, endLoc, v.beginLoc, v.endLoc);} //Normal case 862 else{ 863 //TODO: Bad news! Original MAY have been a length 0 no-call in half-open coordinates. 864 return overlap(beginLoc, endLoc+1, v.beginLoc, v.endLoc); 865 } 866 } 867 // if(v.beginLoc==46397336 || v.beginLoc==46397348){System.out.println("x");} 868 if(v.beginLoc<=beginLoc){return false;} 869 // if(v.beginLoc==46397336 || v.beginLoc==46397348){System.out.println("y");} 870 } 871 // if(v.beginLoc==46397336 || v.beginLoc==46397348){System.out.println("z");} 872 873 return overlap(beginLoc, endLoc, v.beginLoc, v.endLoc); 874 } 875 } 876