jpayne@68
|
1 package clump;
|
jpayne@68
|
2
|
jpayne@68
|
3 import java.io.Serializable;
|
jpayne@68
|
4
|
jpayne@68
|
5 import hiseq.FlowcellCoordinate;
|
jpayne@68
|
6 import shared.KillSwitch;
|
jpayne@68
|
7 import shared.Tools;
|
jpayne@68
|
8 import stream.Read;
|
jpayne@68
|
9 import structures.IntList;
|
jpayne@68
|
10
|
jpayne@68
|
11 class ReadKey implements Serializable, Comparable<ReadKey> {
|
jpayne@68
|
12
|
jpayne@68
|
13 // public static ReadKey makeKeyIfNeeded(Read r){
|
jpayne@68
|
14 // if(r.obj==null){
|
jpayne@68
|
15 // return makeKey(r, true);
|
jpayne@68
|
16 // }
|
jpayne@68
|
17 // return (ReadKey)r.obj;
|
jpayne@68
|
18 // }
|
jpayne@68
|
19
|
jpayne@68
|
20 public static ReadKey makeKey(Read r, boolean setObject){
|
jpayne@68
|
21 assert(r.obj==null);
|
jpayne@68
|
22 try {
|
jpayne@68
|
23 ReadKey rk=new ReadKey(r);
|
jpayne@68
|
24 if(setObject){r.obj=rk;}
|
jpayne@68
|
25 return rk;
|
jpayne@68
|
26 } catch (OutOfMemoryError e) {
|
jpayne@68
|
27 KillSwitch.memKill(e);
|
jpayne@68
|
28 throw new RuntimeException(e);
|
jpayne@68
|
29 }
|
jpayne@68
|
30 }
|
jpayne@68
|
31
|
jpayne@68
|
32 private ReadKey(Read r){
|
jpayne@68
|
33 this(r, 0, 0, true);
|
jpayne@68
|
34 }
|
jpayne@68
|
35
|
jpayne@68
|
36 private ReadKey(Read r, long kmer_, int position_, boolean plus_){
|
jpayne@68
|
37 kmer=kmer_;
|
jpayne@68
|
38 position=position_;
|
jpayne@68
|
39 clump=null;
|
jpayne@68
|
40 assert(!r.swapped());
|
jpayne@68
|
41 flipped=false;
|
jpayne@68
|
42 kmerMinusStrand=!plus_;
|
jpayne@68
|
43
|
jpayne@68
|
44 if(Clump.opticalOnly){
|
jpayne@68
|
45 FlowcellCoordinate fc=FlowcellCoordinate.getFC();
|
jpayne@68
|
46 fc.setFrom(r.id);
|
jpayne@68
|
47 lane=fc.lane;
|
jpayne@68
|
48 tile=fc.tile;
|
jpayne@68
|
49 x=fc.x;
|
jpayne@68
|
50 y=fc.y;
|
jpayne@68
|
51 }
|
jpayne@68
|
52 // expectedErrors=r.expectedErrorsIncludingMate(true);
|
jpayne@68
|
53 }
|
jpayne@68
|
54
|
jpayne@68
|
55 protected ReadKey(){}
|
jpayne@68
|
56
|
jpayne@68
|
57 public void set(long kmer_, int position_, boolean minus_){
|
jpayne@68
|
58 setKmer(kmer_);
|
jpayne@68
|
59 setPosition(position_);
|
jpayne@68
|
60 // setClump(null);
|
jpayne@68
|
61 kmerMinusStrand=minus_;
|
jpayne@68
|
62 }
|
jpayne@68
|
63
|
jpayne@68
|
64 private long setKmer(long kmer_){
|
jpayne@68
|
65 return kmer=kmer_;
|
jpayne@68
|
66 }
|
jpayne@68
|
67
|
jpayne@68
|
68 private int setPosition(int position_){
|
jpayne@68
|
69 return position=position_;
|
jpayne@68
|
70 }
|
jpayne@68
|
71
|
jpayne@68
|
72 public Clump setClump(Clump clump_){
|
jpayne@68
|
73 return clump=clump_;
|
jpayne@68
|
74 }
|
jpayne@68
|
75
|
jpayne@68
|
76 private boolean setFlipped(boolean flipped_){
|
jpayne@68
|
77 assert(flipped!=flipped_);
|
jpayne@68
|
78 return flipped=flipped_;
|
jpayne@68
|
79 }
|
jpayne@68
|
80
|
jpayne@68
|
81 public void clear(){
|
jpayne@68
|
82 setKmer(0);
|
jpayne@68
|
83 setPosition(0);
|
jpayne@68
|
84 setClump(null);
|
jpayne@68
|
85 kmerMinusStrand=false;
|
jpayne@68
|
86 }
|
jpayne@68
|
87
|
jpayne@68
|
88 public void flip(Read r, int k){
|
jpayne@68
|
89 assert(r.swapped()==flipped);
|
jpayne@68
|
90 r.reverseComplement();
|
jpayne@68
|
91 r.setSwapped(!r.swapped());
|
jpayne@68
|
92 setFlipped(!flipped);
|
jpayne@68
|
93 if(r.length()>=k){setPosition(r.length()-position+k-2);}
|
jpayne@68
|
94 assert(r.swapped()==flipped);
|
jpayne@68
|
95 }
|
jpayne@68
|
96
|
jpayne@68
|
97 @Override
|
jpayne@68
|
98 public int compareTo(ReadKey b){
|
jpayne@68
|
99 if(kmer!=b.kmer){return kmer>b.kmer ? -1 : 1;} //Bigger kmers first...
|
jpayne@68
|
100 if(kmerMinusStrand!=b.kmerMinusStrand){return kmerMinusStrand ? 1 : -1;}
|
jpayne@68
|
101 if(position!=b.position){return position<b.position ? 1 : -1;}
|
jpayne@68
|
102 if(Clump.opticalOnly){
|
jpayne@68
|
103 if(lane!=b.lane){return lane-b.lane;}
|
jpayne@68
|
104 if(!spanTiles()){
|
jpayne@68
|
105 if(tile!=b.tile){return tile-b.tile;}
|
jpayne@68
|
106 }
|
jpayne@68
|
107 if(Clump.sortYEarly()){ //Improves speed slightly
|
jpayne@68
|
108 if(y!=b.y){return y-b.y;}
|
jpayne@68
|
109 }
|
jpayne@68
|
110 }
|
jpayne@68
|
111 // if(expectedErrors!=b.expectedErrors){
|
jpayne@68
|
112 // return expectedErrors>b.expectedErrors ? 1 : -1;//Higher quality first
|
jpayne@68
|
113 // }
|
jpayne@68
|
114 return 0;
|
jpayne@68
|
115 }
|
jpayne@68
|
116
|
jpayne@68
|
117 @Override
|
jpayne@68
|
118 public boolean equals(Object b){
|
jpayne@68
|
119 return equals((ReadKey)b, false);
|
jpayne@68
|
120 }
|
jpayne@68
|
121
|
jpayne@68
|
122 @Override
|
jpayne@68
|
123 public int hashCode() {
|
jpayne@68
|
124 int x=(int)((kmer^position)&0xFFFFFFFFL);
|
jpayne@68
|
125 return kmerMinusStrand ? -x : x;
|
jpayne@68
|
126 }
|
jpayne@68
|
127
|
jpayne@68
|
128 /** True if this physically contains b (ignoring mismatches) */
|
jpayne@68
|
129 public boolean physicallyContains(ReadKey b, int aLen, int bLen){
|
jpayne@68
|
130 if(bLen>aLen){return false;}
|
jpayne@68
|
131 if(kmer!=b.kmer){return false;}
|
jpayne@68
|
132 final int dif=position-b.position;
|
jpayne@68
|
133 int bStart=dif, bStop=dif+bLen;
|
jpayne@68
|
134 return bStart>=0 && bStop<=aLen;
|
jpayne@68
|
135 }
|
jpayne@68
|
136
|
jpayne@68
|
137 /** True if this physically contains b as a prefix or suffix (ignoring mismatches).
|
jpayne@68
|
138 * More restrictive than physicallyContains. */
|
jpayne@68
|
139 public boolean physicalAffix(ReadKey b, int aLen, int bLen){
|
jpayne@68
|
140 if(bLen>aLen){return false;}
|
jpayne@68
|
141 if(kmer!=b.kmer){return false;}
|
jpayne@68
|
142 final int dif=position-b.position;
|
jpayne@68
|
143 int bStart=dif, bStop=dif+bLen;
|
jpayne@68
|
144 return (bStart==0 || bStop==aLen) && bStart>=0 && bStop<=aLen;
|
jpayne@68
|
145 }
|
jpayne@68
|
146
|
jpayne@68
|
147 /** Note that this is different than compareTo()==0
|
jpayne@68
|
148 * That's to prevent sortYEarly comparison making things unequal.
|
jpayne@68
|
149 * @param b
|
jpayne@68
|
150 * @return True if equal
|
jpayne@68
|
151 */
|
jpayne@68
|
152 public boolean equals(ReadKey b, boolean containment){
|
jpayne@68
|
153 if(b==null){return false;}
|
jpayne@68
|
154 if(kmer!=b.kmer){return false;}
|
jpayne@68
|
155 if(!containment && (kmerMinusStrand!=b.kmerMinusStrand || position!=b.position)){return false;}
|
jpayne@68
|
156 if(Clump.opticalOnly){
|
jpayne@68
|
157 if(lane!=b.lane){return false;}
|
jpayne@68
|
158 if(!spanTiles()){
|
jpayne@68
|
159 if(tile!=b.tile){return false;}
|
jpayne@68
|
160 }
|
jpayne@68
|
161 }
|
jpayne@68
|
162 return true;
|
jpayne@68
|
163 }
|
jpayne@68
|
164 public boolean equals(ReadKey b){
|
jpayne@68
|
165 return equals(b, false);
|
jpayne@68
|
166 }
|
jpayne@68
|
167
|
jpayne@68
|
168 @Override
|
jpayne@68
|
169 public String toString(){
|
jpayne@68
|
170 return position+","+(kmerMinusStrand ? ",t" : ",f")+","+kmer+"\t"+lane+","+tile+","+x+","+y;
|
jpayne@68
|
171 }
|
jpayne@68
|
172
|
jpayne@68
|
173 public float distance(ReadKey rkb){
|
jpayne@68
|
174 if(lane!=rkb.lane){return FlowcellCoordinate.big;}
|
jpayne@68
|
175
|
jpayne@68
|
176 long a=Tools.absdif(x, rkb.x), b=Tools.absdif(y, rkb.y);
|
jpayne@68
|
177 if(tile!=rkb.tile){
|
jpayne@68
|
178 if(spanTiles()){
|
jpayne@68
|
179 if(spanAdjacentOnly && Tools.absdif(tile, rkb.tile)>1){return FlowcellCoordinate.big;}
|
jpayne@68
|
180 if(spanTilesX && spanTilesY){
|
jpayne@68
|
181 return Tools.min(a, b);
|
jpayne@68
|
182 }else if(spanTilesX){
|
jpayne@68
|
183 return a;
|
jpayne@68
|
184 }else{
|
jpayne@68
|
185 return b;
|
jpayne@68
|
186 }
|
jpayne@68
|
187 }else{
|
jpayne@68
|
188 return FlowcellCoordinate.big;
|
jpayne@68
|
189 }
|
jpayne@68
|
190 }
|
jpayne@68
|
191 return (float)Math.sqrt(a*a+b*b);
|
jpayne@68
|
192 }
|
jpayne@68
|
193
|
jpayne@68
|
194 public boolean near(ReadKey rkb, float dist){
|
jpayne@68
|
195 return distance(rkb)<dist;
|
jpayne@68
|
196 }
|
jpayne@68
|
197
|
jpayne@68
|
198 public boolean nearXY(ReadKey rkb, float dist){
|
jpayne@68
|
199 if(lane!=rkb.lane){return false;}
|
jpayne@68
|
200
|
jpayne@68
|
201 long a=Tools.absdif(x, rkb.x), b=Tools.absdif(y, rkb.y);
|
jpayne@68
|
202 return Tools.min(a,b)<=dist;
|
jpayne@68
|
203 }
|
jpayne@68
|
204
|
jpayne@68
|
205 public int flag;
|
jpayne@68
|
206
|
jpayne@68
|
207 public long kmer;
|
jpayne@68
|
208 /** Position of rightmost base of kmer */
|
jpayne@68
|
209 public int position;
|
jpayne@68
|
210 public boolean flipped;
|
jpayne@68
|
211 public boolean kmerMinusStrand;
|
jpayne@68
|
212 public Clump clump;
|
jpayne@68
|
213 public IntList vars;
|
jpayne@68
|
214 // public float expectedErrors;
|
jpayne@68
|
215
|
jpayne@68
|
216 public int lane, tile, x, y;
|
jpayne@68
|
217
|
jpayne@68
|
218 public static final int overhead=overhead();
|
jpayne@68
|
219 private static int overhead(){
|
jpayne@68
|
220 return 16+ //self
|
jpayne@68
|
221 1*(8)+ //kmer
|
jpayne@68
|
222 1*(4)+ //int fields
|
jpayne@68
|
223 2*(4)+ //booleans
|
jpayne@68
|
224 2*(8)+ //pointers
|
jpayne@68
|
225 4*(4); //flowcell coordinate
|
jpayne@68
|
226 }
|
jpayne@68
|
227
|
jpayne@68
|
228 public static boolean spanTiles(){return spanTilesX || spanTilesY;}
|
jpayne@68
|
229 public static boolean spanTilesX=false;
|
jpayne@68
|
230 public static boolean spanTilesY=false;
|
jpayne@68
|
231 public static boolean spanAdjacentOnly=false;
|
jpayne@68
|
232
|
jpayne@68
|
233 /**
|
jpayne@68
|
234 *
|
jpayne@68
|
235 */
|
jpayne@68
|
236 private static final long serialVersionUID = 1L;
|
jpayne@68
|
237
|
jpayne@68
|
238 }
|