comparison CSP2/CSP2_env/env-d9b9114564458d9d-741b3de822f2aaca6c6caa4325c4afce/opt/bbmap-39.01-1/current/sketch/Comparison.java @ 68:5028fdace37b

planemo upload commit 2e9511a184a1ca667c7be0c6321a36dc4e3d116d
author jpayne
date Tue, 18 Mar 2025 16:23:26 -0400
parents
children
comparison
equal deleted inserted replaced
67:0e9998148a16 68:5028fdace37b
1 package sketch;
2
3 import java.util.Comparator;
4 import java.util.Locale;
5
6 import aligner.Aligner;
7 import prok.GeneCaller;
8 import shared.Tools;
9 import tax.TaxNode;
10
11 public final class Comparison extends SketchObject implements Comparable<Comparison> {
12
13 /*--------------------------------------------------------------*/
14 /*---------------- Constructors ----------------*/
15 /*--------------------------------------------------------------*/
16
17 // public Comparison(CompareBuffer buffer){
18 // this(buffer, null, null);
19 // }
20
21 // public Comparison(Sketch a_, Sketch b_){
22 // this(null, a_, b_);
23 // }
24
25 public Comparison(CompareBuffer buffer, Sketch a_, Sketch b_){
26
27 a=a_;
28 b=b_;
29
30 if(buffer!=null){setFrom(buffer);}
31
32 if(b!=null){
33 taxName=b.taxName();
34 taxID=b.taxID;
35 }
36
37 // System.err.println(this);
38 // System.err.println(b.present);
39 }
40
41 /*--------------------------------------------------------------*/
42 /*---------------- Mutators ----------------*/
43 /*--------------------------------------------------------------*/
44
45 public void setFrom(CompareBuffer buffer){
46 hits=buffer.hits();
47 multiHits=buffer.multiHits();
48 unique2=buffer.unique2();
49 unique3=buffer.unique3();
50 noHits=buffer.noHits();
51
52 contamHits=buffer.contamHits();
53 contam2Hits=buffer.contam2Hits();
54 multiContamHits=buffer.multiContamHits();
55
56 refDivisor=buffer.refDivisor();
57 queryDivisor=buffer.queryDivisor();
58
59 refSize=buffer.refSize();
60 querySize=buffer.querySize();
61
62 depth=buffer.depth();
63 depth2=buffer.depth2();
64 float x=buffer.avgRefHits();
65 if(x>0){avgRefHits=x;}
66 // volume=volume0();
67 score=score0();
68
69 hits1=buffer.hits1();
70 qSeen1=buffer.qSeen1();
71 rSeen1=buffer.rSeen1();
72 }
73
74 public void recompare(CompareBuffer buffer, int[][] taxHits, int contamLevel){
75
76 // for(int[] row : taxHits){
77 // if(row!=null){
78 // System.err.println(Arrays.toString(row));
79 // }
80 // }//Tested; correctly indicates most rows have octopus but some have other things.
81
82 assert(a.merged());
83 // int oldContam2=contam2Hits;
84 int x=a.countMatches(b, buffer, a.compareBitSet(), false, taxHits, contamLevel);
85 assert(x==hits);
86 setFrom(buffer);
87 // contam2Hits=oldContam2;
88 }
89
90 /*--------------------------------------------------------------*/
91 /*---------------- Methods ----------------*/
92 /*--------------------------------------------------------------*/
93
94 @Override
95 public boolean equals(Object b){
96 if(b==null || b.getClass()!=this.getClass()){return false;}
97 return scoreComparator.compare(this, (Comparison)b)==0;
98 }
99
100 // //WKID
101 // public float wkid(){return idMinDivisor();}
102 // public float idMinDivisor(){
103 // return hits/(float)minDivisor();
104 // }
105
106 // public float k1Fraction(){
107 // return a.k1Fraction();
108 // }
109
110 // //KID
111 // public float kid(){return idMaxDivisor();}
112 // public float idMaxDivisor(){
113 // return hits/(float)maxDivisor();
114 // }
115
116 public float idQueryDivisor(){
117 return hits/(float)(Tools.max(1, refDivisor));
118 }
119
120 public float idRefDivisor(){
121 return hits/(float)(Tools.max(1, refDivisor));
122 }
123
124 public float completeness(){
125 float complt=Tools.min(1, (queryDivisor-contamHits)/(float)Tools.max(1, refDivisor));
126 return complt;
127 // float c2=hits/(float)refDivisor;
128 // assert(queryDivisor-contamHits>=hits);
129 // assert(c1>=c2);
130 // System.err.println(hits+", "+contamHits+", "+refDivisor+", "+queryDivisor+", "+c1+", "+c2);
131 // return Tools.max(c1, c2);
132 // float kid=idMaxDivisor(), wkid=idMinDivisor();
133 // return kid==0 ? 0 : kid/wkid;
134 }
135
136 public float contamFraction(){
137 return Tools.min(1, contamHits/(float)Tools.max(1, queryDivisor));
138 }
139
140 public float contam2Fraction(){
141 return Tools.min(1, contam2Hits/(float)Tools.max(1, queryDivisor));
142 }
143
144 public float uContamFraction() {
145 int uContamHits=contamHits-multiContamHits;
146 return Tools.min(1, uContamHits/(float)Tools.max(1, queryDivisor));
147 }
148
149
150
151 /*--------------------------------------------------------------*/
152
153 final float wkid(){
154 final int div=minDivisor();
155 return hits/(float)div;
156 }
157 final float kid(){
158 final int div=maxDivisor();
159 return hits/(float)div;
160 }
161 final float aniOld(){
162 float wkid=wkid();
163 // final float ani=wkidToAni(wkid, k1Fraction());
164 final float ani=wkidToAni(wkid);
165 return ani;
166 }
167 final float ani(){
168 if(hits<1){return 0;}
169 final float ani;
170 if(k2>0 && useToValue2){
171 float ani1=ani1();
172 float ani2=ani2();
173 // ani=0.5f*(ani1+ani2);
174 ani=0.5f*(Tools.max(0.9f*ani2, ani1)+Tools.max(0.8f*ani1, ani2));
175 // return (ani1*qSeen1+ani2*qSeen2())/queryDivisor;
176
177 // System.err.println("ani="+ani+"aniOld="+aniOld()+", ani1="+ani1()+", ani2="+ani2()+", anid="+(float)aniDual()+"\n"
178 //// +"gf="+(float)gf+", wkid1="+wkid1+", wkid2="+wkid2+"\n"
179 // + "k1f="+k1Fraction()+", hits="+hits+", hits1="+hits1+", hits2="+hits2()+", qSeen1()="+qSeen1()+", rSeen1()="+rSeen1()+"\n"
180 // + "qSeen2()="+qSeen2()+", rSeen2()="+rSeen2()+", minDivisor1()="+minDivisor1()+", minDivisor2()="+minDivisor2()+"\n");
181 }else{
182 ani=aniOld();
183 }
184 return ani;
185 }
186
187 final float wkid1(){
188 final int div=minDivisor1();
189 return hits1()/(float)div;
190 }
191 final float kid1(){
192 final int div=maxDivisor1();
193 return hits1()/(float)div;
194 }
195 final float ani1(){
196 float wkid=wkid1();
197 final float ani=wkidToAniExact(wkid, k);
198 return ani;
199 }
200
201 final float wkid2(){
202 final int div=minDivisor2();
203 return hits2()/(float)div;
204 }
205 final float kid2(){
206 final int div=maxDivisor2();
207 return hits2()/(float)div;
208 }
209 final float ani2(){
210 assert(k2>0);
211 float wkid=wkid2();
212 final float ani=wkidToAniExact(wkid, k2);
213 return ani;
214 }
215
216 final float aniDual(){
217 assert(k2>0);
218 float wkid1=wkid1();
219 float wkid2=wkid2();
220 float ratio=(wkid1/wkid2);
221 float exp=1f/(k-k2);//TODO - make this initialized
222 double ani=Math.pow(ratio, exp);
223 double gf=wkid2/Math.pow(ani, k2);
224
225 // System.err.println("ani="+ani()+"aniOld="+aniOld()+", ani1="+ani1()+", ani2="+ani2()+", anid="+(float)ani+"\n"
226 // +"gf="+(float)gf+", wkid1="+wkid1+", wkid2="+wkid2+"\n"
227 // + "k1f="+k1Fraction()+", hits="+hits+", hits1="+hits1+", hits2="+hits2()+", qSeen1()="+qSeen1()+", rSeen1()="+rSeen1()+"\n"
228 // + "qSeen2()="+qSeen2()+", rSeen2()="+rSeen2()+", minDivisor1()="+minDivisor1()+", minDivisor2()="+minDivisor2()+"\n");
229
230 return (float)ani;
231 }
232
233 /*--------------------------------------------------------------*/
234
235 int hits1(){return hits1;}
236 int qSeen1(){return qSeen1;}
237 int rSeen1(){return rSeen1;}
238 int minDivisor1(){return Tools.max(1, Tools.min(qSeen1, rSeen1));}
239 int maxDivisor1(){return Tools.max(1, qSeen1, rSeen1);}
240
241 int hits2(){return hits-hits1;}
242 int qSeen2(){return queryDivisor-qSeen1;}
243 int rSeen2(){return refDivisor-rSeen1;}
244 int minDivisor2(){return Tools.max(1, Tools.min(qSeen2(), rSeen2()));}
245 int maxDivisor2(){return Tools.max(1, qSeen2(), rSeen2());}
246
247 /*--------------------------------------------------------------*/
248
249 // public float aniOld(){
250 // if(hits<1){return 0;}
251 //
252 //// double wkid=aniFromWKID ? idMinDivisor() : idMaxDivisor();
253 // double wkid=idMinDivisor();
254 // return wkidToAni(wkid, k1Fraction());
255 //
256 //// final float rID=hits/(float)(refDivisor);
257 //// final float qID=hits/(float)(queryDivisor-contamHits);
258 //// final float wkid2=Tools.max(qID, rID);
259 //// final float ani=wkidToAni(wkid2);
260 ////
261 ////// System.err.println("rid: "+wkidToAni(rID)+", qid: "+wkidToAni(qID)+", qid2: "+wkidToAni(hits/(float)(queryDivisor)));
262 ////
263 //// return ani;
264 // }
265
266 int minDivisor(){return Tools.max(1, Tools.min(refDivisor, queryDivisor));}
267 int maxDivisor(){return Tools.max(1, refDivisor, queryDivisor);}
268
269 private float score0_old(){
270 long est=useSizeEstimate ? genomeSizeEstimate() : genomeSizeKmers();
271 float wkid=wkid();
272 float kid=kid();
273 float complt=completeness();
274 float contam=contamFraction();
275 float refHits=Tools.max(avgRefHits, 1f);
276 float refHitMult=1f+(0.6f/(float)Math.sqrt(refHits+1));
277 return (float)((Math.log(hits+2)*.25f+0.5f)*(refHitMult*0.2*Math.log(hits+2+(1.2*uHits()+0.25*unique2()+0.1*unique3()))
278 *Math.sqrt(40*(20000+hits+uHits())*(wkid*kid*Math.pow(est*complt, 0.2)*(1-contam*0.1)))+0.1));
279 }
280
281 private float score0(){
282 final long est=useSizeEstimate ? genomeSizeEstimate() : genomeSizeKmers();
283 final float wkid=wkid();
284 final float kid=kid();
285 final float ani=ani();
286 final float complt=completeness();
287 final float contam=contamFraction();
288 final float refHits=Tools.max(avgRefHits, 1f);
289 final float refHitMult=1f+(0.6f/(float)Math.sqrt(refHits+1));
290 final float uhits=uHits();
291 final float uhits2=unique2();
292 final float uhits3=unique3();
293 final float contamMult=(1-contam*0.95f);
294 final float estMult=(float)(Math.pow(est, 0.2)*Math.sqrt(complt));
295 final float aniMult=(float)(ani*Math.sqrt(wkid*kid));
296
297 final float hitsSum=1+hits+uhits+0.5f*uhits2+0.25f*uhits3;
298
299 final float score=(float)(Math.log(Tools.max(1.2f, hits-1))*hitsSum*refHitMult*contamMult*aniMult*estMult);//+(Math.log(hitsSum+1)*wkid*complt));
300 return (float)(8*Math.sqrt(score));
301 }
302
303 private long range(){//TODO Make sure these are calculated correctly; it seems like one divisor might be 1 higher than necessary.
304 long maxA=a.keys[Tools.max(0, queryDivisor-1)];
305 long maxB=b.keys[Tools.max(0, refDivisor-1)];
306 // assert(false) : Tools.max(0, queryDivisor-1)+", "+Tools.max(0, refDivisor-1)+
307 // ", "+a.array[Tools.max(0, queryDivisor-1)]+", "+b.array[Tools.max(0, refDivisor-1)]+", "+Tools.max(maxA, maxB);//+"\n\n"+Arrays.toString(a.array)+"\n\n"+Arrays.toString(b.array);
308 return Tools.min(maxA, maxB);
309 }
310
311 private static double eValue(int hits, int minDiv, int maxDiv, long range){
312 if(hits>=range || maxDiv>=range){return 1.0;}
313 double probHit=maxDiv/(double)range;//Saturation of range
314 // double probNoHit=1-probHit;
315 double eValue=Math.pow(probHit, hits); //This is a simplification, assuming hits are very improbable.
316 //Note that this does not take into account minDiv, the number of attempts... but it should.
317 // System.err.println("hits="+hits+", minDiv="+minDiv+", maxDiv="+maxDiv+", range="+range+", eValue="+eValue);
318 return eValue;
319 }
320
321 public double eValue(){
322 double eValue=eValue1()*eValue2();
323 // System.err.println("eValue="+eValue);
324 return eValue;
325 }
326
327 public double eValue1(){
328 long range0=range();
329 int missingBits=64-(aminoOrTranslate() ? 5 : 2)*k;
330 double quantizer=1.0/(aminoOrTranslate() ? Math.pow(2, missingBits*aaBitValue) : 1L<<missingBits);
331 int hits=hits1;
332 int minDiv=Tools.min(qSeen1, rSeen1);
333 int maxDiv=Tools.max(qSeen1, rSeen1);
334 long range=Tools.max((long)Math.ceil(range0*quantizer), maxDiv);
335 return eValue(hits, minDiv, maxDiv, range);
336 }
337
338 public double eValue2(){
339 if(k2<1){return 1.0;}
340
341 long range0=range();
342 int missingBits=64-(aminoOrTranslate() ? 5 : 2)*k2;
343 double quantizer=1.0/(aminoOrTranslate() ? Math.pow(2, missingBits*aaBitValue) : 1L<<missingBits);
344 int hits=hits2();
345 int minDiv=Tools.min(qSeen2(), rSeen2());
346 int maxDiv=Tools.max(qSeen2(), rSeen2());
347 long range=Tools.max((long)Math.ceil(range0*quantizer), maxDiv);
348 // assert(false) : missingBits+", "+quantizer+", "+range0+", "+range+", "+eValue(hits, minDiv, maxDiv, range);
349 return eValue(hits, minDiv, maxDiv, range);
350 }
351
352 public String scoreS(){
353 float x=score;
354 return format3(x);
355 }
356
357 public double depth(boolean observedToActual){
358 return observedToActual ? Tools.observedToActualCoverage(depth) : depth;
359 }
360
361 public double depth2(boolean observedToActual){
362 return observedToActual ? Tools.observedToActualCoverage(depth2) : depth2;
363 }
364
365 public String depthS(boolean observedToActual){
366 float x=depth;
367 if(observedToActual){x=(float)Tools.observedToActualCoverage(x);}
368 return format3(x);
369 }
370
371 public float avgRefHits(){
372 return avgRefHits;
373 }
374
375 public String avgRefHitsS(){
376 return format2(avgRefHits);
377 }
378
379 public String depth2S(boolean observedToActual){
380 float x=depth2;
381 if(observedToActual){
382 x=(float)(Tools.observedToActualCoverage(depth)*(depth2/depth));
383 }
384 return format3(x);
385 }
386
387 public String volumeS(){
388 double x=volume()*0.001;
389 return format3(x);
390 }
391
392 static String format3(double x){
393 if(x>=999.95){
394 return(""+(long)Math.round(x));
395 }else if(x>=99.995){
396 return String.format(Locale.ROOT, "%.1f", x);
397 }else if(x>=9.9995){
398 return String.format(Locale.ROOT, "%.2f", x);
399 }
400 return String.format(Locale.ROOT, "%.3f", x);
401 }
402
403 static String format2(double x){
404 if(x>=999.95){
405 return(""+(long)Math.round(x));
406 }else if(x>=99.995){
407 return String.format(Locale.ROOT, "%.1f", x);
408 }else if(x>=9.9995){
409 return String.format(Locale.ROOT, "%.2f", x);
410 }
411 return String.format(Locale.ROOT, "%.2f", x);
412 }
413
414 float volume(){
415 return Tools.max(1f, depth)*hits;
416 }
417
418 @Override
419 public String toString(){
420 return "hits="+hits+", refDivisor="+refDivisor+", queryDivisor="+queryDivisor+", refSize="+refSize+", querySize="+querySize+
421 ", contamHits="+contamHits+", contam2Hits="+contam2Hits+", multiContamHits="+multiContamHits+", depth="+depth+", depth2="+depth2+", volume="+volume()+
422 ", hits="+hits+", multiHits="+multiHits+", unique2="+unique2+", unique3="+unique3+", noHits="+noHits+", taxID="+taxID+", taxName="+taxName;
423 }
424
425 /*--------------------------------------------------------------*/
426 /*---------------- Getters ----------------*/
427 /*--------------------------------------------------------------*/
428
429 // public boolean passesFilter(TaxFilter white, TaxFilter black){
430 // if(white==null && black==null){return true;}
431 // int id=taxID();
432 // String s=name();
433 // return passesFilter(white, id, s) && passesFilter(black, id, s);
434 // }
435 //
436 // private boolean passesFilter(TaxFilter filter, int id, String s){
437 // if(filter==null){return true;}
438 // if(id>0 && !filter.passesFilter(id)){return false;}
439 // if(s!=null && !filter.passesFilterByNameOnly(s)){return false;}
440 // return true;
441 // }
442
443 public String name(){return taxName!=null ? taxName : name0()!=null ? name0() : fname()!=null ? fname() : ""+taxID();}
444 public String taxName(){return taxName;}
445 String name0(){return b.name0();}
446 String fname(){return b.fname();}
447
448 // public int taxID(){return b.taxID<minFakeID ? b.taxID : 0;}
449 public int taxID(){return (taxID<minFakeID && taxID>=0) ? taxID : -1;}
450 long imgID(){return (b.imgID>0 ? b.imgID : -1);}
451
452 long genomeSizeBases(){return b.genomeSizeBases;}
453 long genomeSizeKmers(){return b.genomeSizeKmers;}
454 long genomeSequences(){return b.genomeSequences;}
455 long genomeSizeEstimate(){return b.genomeSizeEstimate();}
456 float gc(){return b.gc();}
457 boolean hasGC(){return b.baseCounts!=null;}
458
459 public boolean hasSSU() {
460 return (a.r16S()!=null && b.r16S()!=null) || (a.r18S()!=null && b.r18S()!=null);
461 }
462 public boolean hasSSUIdentity() {
463 return ssuIdentity>=0;
464 }
465 public boolean needsAlignment() {
466 return hasSSU() && !hasSSUIdentity();
467 }
468 public boolean hasQueryTaxID() {
469 return a.taxID>0 && a.taxID<minFakeID;
470 }
471
472
473 public int uHits() {return hits-multiHits;}
474
475 /** Common ancestor TaxID, if both Sketches have a TaxID */
476 public int commonAncestor() {
477 if(a.taxID<1 || b.taxID<1){return -1;}
478 assert(taxtree!=null);
479 int id=taxtree.commonAncestor(a.taxID, b.taxID);
480 return id;
481 }
482
483 /** Common ancestor node tax level, if both Sketches have a TaxID */
484 public String commonAncestorLevel() {
485 int id=commonAncestor();
486 if(id<1){return ".";}
487 TaxNode tn=taxtree.getNode(id);
488 while(!tn.isRanked() && tn.pid!=tn.id){tn=taxtree.getNode(tn.pid);}
489 String s=tn.levelStringExtended(false);
490 return s;
491 }
492
493 /** Common ancestor node tax level, if both Sketches have a TaxID */
494 public int commonAncestorLevelInt() {
495 int id=commonAncestor();
496 if(id<1){return 0;}
497 TaxNode tn=taxtree.getNode(id);
498 while(!tn.isRanked() && tn.pid!=tn.id){tn=taxtree.getNode(tn.pid);}
499 return tn.levelExtended;
500 }
501
502 /*--------------------------------------------------------------*/
503 /*---------------- Comparators ----------------*/
504 /*--------------------------------------------------------------*/
505
506
507
508 static class ScoreComparator implements Comparator<Comparison>{
509
510 @Override
511 public int compare(Comparison a, Comparison b) {
512 {
513 float pa=a.score, pb=b.score;
514 if(pa>pb){
515 return 1;
516 }else if (pa<pb){
517 return -1;
518 }
519 }
520
521 int x=a.hits-b.hits;
522 if(x!=0){return x;}
523 x=b.minDivisor()-a.minDivisor();
524 if(x!=0){return x;}
525 x=b.maxDivisor()-a.maxDivisor();
526 if(x!=0){return x;}
527 x=b.refDivisor-a.refDivisor;
528 if(x!=0){return x;}
529 x=a.taxID()-b.taxID();
530 if(x!=0){return x;}
531 if(a.name0()!=null && b.name0()!=null){
532 return a.name0().compareTo(b.name0());
533 }
534 if(a.taxName()!=null && b.taxName()!=null){
535 return a.taxName().compareTo(b.taxName());
536 }
537 return 0;
538 }
539
540 @Override
541 public String toString(){return "sortByScore";}
542
543 }
544
545 static class DepthComparator implements Comparator<Comparison>{
546
547 @Override
548 public int compare(Comparison a, Comparison b) {
549 final float da=Tools.max(0.1f, a.depth-0.5f), db=Tools.max(0.1f, b.depth-0.5f);
550 final float sa, sb;
551 if(sqrt){
552 sa=da*(float)Math.sqrt(a.score);
553 sb=db*(float)Math.sqrt(b.score);
554 }else{
555 sa=da*a.score;
556 sb=db*b.score;
557 }
558 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
559 }
560
561 @Override
562 public String toString(){return "sortByDepth";}
563
564 }
565
566 static class Depth2Comparator implements Comparator<Comparison>{
567
568 @Override
569 public int compare(Comparison a, Comparison b) {
570 final float da=Tools.max(0.1f, a.depth2-0.8f), db=Tools.max(0.1f, b.depth2-0.8f);
571 final float sa, sb;
572 if(sqrt){
573 sa=da*(float)Math.sqrt(a.score);
574 sb=db*(float)Math.sqrt(b.score);
575 }else{
576 sa=da*a.score;
577 sb=db*b.score;
578 }
579 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
580 }
581
582 @Override
583 public String toString(){return "sortByDepth2";}
584
585 }
586
587 static class VolumeComparator implements Comparator<Comparison>{
588
589 @Override
590 public int compare(Comparison a, Comparison b) {
591 final float da=a.volume(), db=b.volume();
592 final float sa, sb;
593 if(sqrt){
594 sa=da*(float)Math.sqrt(a.score);
595 sb=db*(float)Math.sqrt(b.score);
596 }else{
597 sa=da*a.score;
598 sb=db*b.score;
599 }
600 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
601 }
602
603 @Override
604 public String toString(){return "sortByVolume";}
605
606 }
607
608 static class KIDComparator implements Comparator<Comparison>{
609
610 @Override
611 public int compare(Comparison a, Comparison b) {
612 final float sa=a.kid(), sb=b.kid();
613 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
614 }
615
616 @Override
617 public String toString(){return "sortByKID";}
618
619 }
620
621 static class WKIDComparator implements Comparator<Comparison>{
622
623 @Override
624 public int compare(Comparison a, Comparison b) {
625 final float sa=a.wkid(), sb=b.wkid();
626 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
627 }
628
629 @Override
630 public String toString(){return "sortByWKID";}
631
632 }
633
634 static class SSUComparator implements Comparator<Comparison>{
635
636 @Override
637 public int compare(Comparison a, Comparison b) {
638 // if((a.has16S() || a.has18S()) && !a.hasSSUIdentity()){
639 // synchronized(a){a.ssuIdentity();}
640 // assert(a.hasSSUIdentity());
641 // }
642 // if((b.has16S() || b.has18S()) && !b.hasSSUIdentity()){
643 // synchronized(b){b.ssuIdentity();}
644 // assert(b.hasSSUIdentity());
645 // }
646
647 if(a.hasSSUIdentity() && b.hasSSUIdentity()){
648 final float sa=a.ssuIdentity(), sb=b.ssuIdentity();
649 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
650 }else if(a.hasSSUIdentity()){
651 return 1;
652 }else if(b.hasSSUIdentity()){
653 return -1;
654 }else{
655 return scoreComparator.compare(a, b);
656 }
657
658 }
659
660 @Override
661 public String toString(){return "sortBySSU";}
662
663 }
664
665 static class HitsComparator implements Comparator<Comparison>{
666
667 @Override
668 public int compare(Comparison a, Comparison b) {
669 final float sa=a.hits(), sb=b.hits();
670 return sa>sb ? 1 : sa<sb ? -1 : scoreComparator.compare(a, b);
671 }
672
673 @Override
674 public String toString(){return "sortByHits";}
675
676 }
677
678 @Override
679 public int compareTo(Comparison b) {
680 assert(false) : "Please use comparators instead.";
681 return scoreComparator.compare(this, b);
682 }
683
684 @Override
685 public int hashCode() {
686 assert(false) : "TODO";
687 return super.hashCode();
688 }
689
690 public static final ScoreComparator scoreComparator=new ScoreComparator();
691 public static final DepthComparator depthComparator=new DepthComparator();
692 public static final Depth2Comparator depth2Comparator=new Depth2Comparator();
693 public static final VolumeComparator volumeComparator=new VolumeComparator();
694 public static final KIDComparator KIDComparator=new KIDComparator();
695 public static final SSUComparator SSUComparator=new SSUComparator();
696 public static final WKIDComparator WKIDComparator=new WKIDComparator();
697 public static final HitsComparator HitsComparator=new HitsComparator();
698 private static final boolean sqrt=false;
699 private static final double aaBitValue=0.86438561897747246957406388589788; //(log(20)/log(2))/5;
700
701 /*--------------------------------------------------------------*/
702
703 int hits(){return hits;}
704 int multiHits(){return multiHits;}
705 int noHits(){return noHits;}
706 int unique2(){return unique2;}
707 int unique3(){return unique3;}
708
709 float depth(){return depth;}
710 float depth2(){return depth2;}
711 float score(){return score;}
712
713 int contamHits(){return contamHits;}
714 int contam2Hits(){return contam2Hits;}
715 int multiContamHits(){return multiContamHits;}
716
717 int queryDivisor(){return queryDivisor;}
718 int refDivisor(){return refDivisor;}
719
720 int querySize(){return querySize;}
721 int refSize(){return refSize;}
722
723 int ssuType(){return has18S() ? 18 : has16S() ? 16 : 0;}
724 int ssuLen(){return has18S() ? b.r18SLen() : has16S() ? b.r16SLen() : 0;}
725 boolean has16S(){return a.r16S()!=null && b.r16S()!=null;}
726 boolean has18S(){return a.r18S()!=null && b.r18S()!=null;}
727
728 float ssuIdentity(){
729 if(ssuIdentity>0){return ssuIdentity;}
730 if(has18S()){ssuIdentity=calcIdentity(a.r18S(), b.r18S());}
731 else if(has16S()){ssuIdentity=calcIdentity(a.r16S(), b.r16S());}
732 return ssuIdentity;
733 }
734
735 private static float calcIdentity(byte[] ssuA, byte[] ssuB){
736 //assert(false);
737 if(ssuA.length>ssuB.length){
738 byte[] c=ssuA;
739 ssuA=ssuB;
740 ssuB=c;
741 }
742 if(useSSA){
743 Aligner ssa=(useSSA3 ? GeneCaller.getSSA3() : GeneCaller.getSSA());
744 int[] max=ssa.fillUnlimited(ssuA, ssuB, 0, ssuB.length-1, 0);
745 if(max==null){return 0;}
746
747 final int rows=max[0];
748 final int maxCol=max[1];
749 final int maxState=max[2];
750
751 //returns {score, bestRefStart, bestRefStop}
752 //padded: {score, bestRefStart, bestRefStop, padLeft, padRight};
753 int[] score=ssa.score(ssuA, ssuB, 0, ssuB.length-1, rows, maxCol, maxState);
754 int rstart=score[1];
755 int rstop=score[2];
756
757 // byte[] match=ssa.traceback(ssuA, ssuB, 0, ssuB.length-1, rows, maxCol, maxState);
758 // float id=Read.identity(match);
759 float id=ssa.tracebackIdentity(ssuA, ssuB, 0, ssuB.length-1, rows, maxCol, maxState, null);
760 return id;
761 }else{
762 GlocalAligner ga=new GlocalAligner();
763 return ga.alignForward(ssuA, ssuB);
764 }
765 }
766
767 /*--------------------------------------------------------------*/
768 /*---------------- Fields ----------------*/
769 /*--------------------------------------------------------------*/
770
771 public Sketch a, b;
772
773 String taxName;
774 int taxID;
775
776 private int hits;
777 private int multiHits;
778 private int unique2;
779 private int unique3;
780 private int noHits;
781
782 private float depth;
783 private float depth2;
784 private float avgRefHits;
785 private float score;
786
787 private int contamHits;
788 private int contam2Hits;
789 private int multiContamHits;
790
791 private int refDivisor;
792 private int queryDivisor;
793
794 private int refSize;
795 private int querySize;
796
797 private int hits1;
798 private int qSeen1;
799 private int rSeen1;
800
801 private float ssuIdentity=-1;
802
803 }