Source code: jalview/annotation/FeatureSet.java
1 package jalview.annotation;
2
3 import java.util.*;
4
5 import jalview.gui.schemes.*;
6 import jalview.gui.*;
7 import jalview.util.*;
8
9 public class FeatureSet extends SeqFeature implements FeatureSetI {
10
11 private Vector features;
12
13 public FeatureSet() {
14 setStart(100000000); // This not good
15 setEnd(-100000000); // ditto
16 features = new Vector();
17 }
18
19 public int size() {
20 return features.size();
21 }
22
23 public void addFeature(SeqFeatureI feature) {
24 features.addElement(feature);
25
26 if (feature.getStart() < start) {
27 setStart(feature.getStart());
28 }
29
30 if (feature.getEnd() > end) {
31 setEnd(feature.getEnd());
32 }
33
34 }
35
36 public void deleteFeature(SeqFeatureI feature) {
37 if (features.contains(feature)) {
38 features.removeElement(feature);
39 _setEnds();
40 }
41 }
42
43 public SeqFeatureI deleteFeatureAt(int i) {
44 if (i < size()) {
45 SeqFeatureI sf = getFeatureAt(i);
46 features.removeElementAt(i);
47 _setEnds();
48 return sf;
49 }
50 return null;
51 }
52
53 public SeqFeatureI getFeatureAt(int i) {
54 return (SeqFeatureI)features.elementAt(i);
55 }
56
57 public void setFeatureAt(int i,SeqFeatureI sf) {
58 features.setElementAt(sf,i);
59 // SMJS Think that the ends should be redetermined
60 // but its slow. Added then removed line below
61 // _setEnds();
62 }
63
64 public Vector getFeatures() {
65 return features;
66 }
67
68 public Vector getFeatures(long start, long end) {
69 Vector tmp = new Vector();
70
71 for (int i = 0; i < size() ;i++) {
72 SeqFeatureI sf = getFeatureAt(i);
73 if (sf.getEnd() >= start && sf.getStart() <= end) {
74 tmp.addElement(sf);
75 }
76 }
77 return tmp;
78 }
79
80 // Grouping methods
81 public Hashtable hashFeatures() {
82 Hashtable fhash = new Hashtable();
83
84 for (int i=0; i < size(); i++) {
85 SeqFeatureI sf = getFeatureAt(i);
86 String type = sf.getType();
87
88 if (fhash.containsKey(type)) {
89 FeatureSet fset = (FeatureSet)fhash.get(type);
90 fset.addFeature(sf);
91 fhash.put(type,fset);
92 } else {
93 FeatureSet fset = new FeatureSet();
94 fset.addFeature(sf);
95 fhash.put(type,fset);
96 }
97 }
98
99 return fhash;
100 }
101
102 public void expand(FeatureSetI newfset) {
103
104 for (int i=0; i < size(); i++) {
105 SeqFeatureI sf = getFeatureAt(i);
106
107 if (sf instanceof FeatureSetI) {
108 ((FeatureSetI)sf).expand(newfset);
109 } else {
110 newfset.addFeature(sf);
111 }
112 }
113 }
114 public void group() {
115 Hashtable fhash = hashFeatures();
116 Vector newfeatures = new Vector();
117 Enumeration e = fhash.keys();
118 FeatureTypes ftypes = new FeatureTypes();
119 while (e.hasMoreElements()) {
120
121 FeatureSet fset = (FeatureSet)fhash.get(e.nextElement());
122 FeatureProperty fp= ftypes.getType(fset.getType());
123 if (fp != null) {
124 newfeatures.addElement(fset);
125 System.out.println("Making new feature set " + fset.getType());
126 }
127 }
128
129 this.features = newfeatures;
130 this.sort_by_type();
131 }
132
133 public void clump() {
134 Vector features = new Vector();
135
136 for (int i=0; i < size(); i++) {
137 boolean found = false;
138 for (int j=0; j < features.size(); j++) {
139 if (((FeatureSet)features.elementAt(j)).overlaps(getFeatureAt(i))) {
140 ((FeatureSet)features.elementAt(j)).addFeature(getFeatureAt(i));
141 found = true;
142 j = features.size();
143 }
144 }
145 if (!found) {
146 FeatureSet f = new FeatureSet();
147 f.addFeature(getFeatureAt(i));
148 features.addElement(f);
149 }
150 }
151 this.features = features;
152 }
153
154 public void makeSetFeatures() {
155 FeatureTypes ftypes = new FeatureTypes();
156 Vector newfset = new Vector();
157
158 for (int i=0; i < size(); i++) {
159 SeqFeatureI sf = getFeatureAt(i);
160 String type = sf.getType();
161
162 FeatureProperty fp = ftypes.getType(type);
163 if (fp != null) {
164 if (fp.getStyle() == FeatureProperty.GENE) {
165 Vector fvec = makeGeneSets(sf);
166 if (fvec != null) {
167 for (int ii=0; ii < fvec.size(); ii++) {
168 newfset.addElement(fvec.elementAt(ii));
169 }
170 }
171 } else if (fp.getStyle() == FeatureProperty.HOMOL) {
172 Vector fvec = makeHomolSets(sf);
173 if (fvec != null) {
174 for (int ii=0; ii < fvec.size(); ii++) {
175 newfset.addElement(fvec.elementAt(ii));
176 }
177 }
178 } else {
179 newfset.addElement(sf);
180 }
181 }
182 }
183
184 this.features = newfset;
185
186 }
187
188 public void sort_by_type() {
189 FeatureSet newfset = new FeatureSet();
190 FeatureTypes ftypes = new FeatureTypes();
191
192 for (int i=0; i < ftypes.size(); i++) {
193 FeatureProperty type = ftypes.getTypeAt(i);
194 String typestr = type.getType();
195
196 for (int j=0; j < size(); j++) {
197 String ftype = getFeatureAt(j).getType();
198 if (typestr.equals(ftype)) {
199 newfset.addFeature(getFeatureAt(j));
200 }
201 }
202 }
203 this.features = newfset.features;
204 }
205
206 public Vector makeHomolSets(SeqFeatureI sf) {
207 if (sf instanceof FeatureSetI) {
208 FeatureSetI fset = (FeatureSetI)sf;
209 Hashtable ghash = new Hashtable();
210
211 for (int i=0; i < fset.size(); i++) {
212 SeqFeatureI sf2 = fset.getFeatureAt(i);
213 if (ghash.containsKey(sf2.getName())) {
214 FeatureSet tmp = (FeatureSet)ghash.get(sf2.getName());
215 tmp.addFeature(sf2);
216 ghash.put(sf2.getName(),tmp);
217 } else {
218 FeatureSet tmp = new FeatureSet();
219 tmp.addFeature(sf2);
220 ghash.put(sf2.getName(),tmp);
221 }
222 }
223
224 Enumeration e = ghash.keys();
225 FeatureSet newfset2 = new FeatureSet();
226 while (e.hasMoreElements()) {
227
228 FeatureSetI sf2 = (FeatureSetI)ghash.get(e.nextElement());
229 FeatureSetI sf3 = _splitHomols(sf2);
230
231 // if (_countIntrons(sf2) > 0) {
232 for (int k=0; k < sf3.size(); k++) {
233 newfset2.addFeature(sf3.getFeatureAt(k));
234 }
235 //}
236 }
237 return newfset2.getFeatures();
238 } else {
239 return null;
240 }
241 }
242 /**
243 * Method to split a HOMOL feature set into pieces which are more or less
244 * contiguous (less than 10 bases between features).
245 */
246 public FeatureSetI _splitHomols(SeqFeatureI sf2) {
247 FeatureSetI fset = (FeatureSetI)sf2;
248 long[] starts = new long[fset.size()];
249 SeqFeatureI[] f = new SeqFeatureI[fset.size()];
250
251 // System.out.println("_splitHomols called");
252 // Sort the feature set by start coord
253 for (int i=0; i < fset.size(); i++) {
254
255 starts[i] = fset.getFeatureAt(i).getStart();
256 f[i] = fset.getFeatureAt(i);
257 }
258
259 QuickSort.sort(starts,f);
260
261 FeatureSet newfset = new FeatureSet();
262
263 for (int i=0; i < fset.size(); i++) {
264 newfset.addFeature(f[i]);
265 }
266
267 fset = newfset;
268
269 // Now partition the feature set into
270 // continuous pieces
271 FeatureSet newsets = new FeatureSet();
272 int gap = 10;
273 for (int i=0; i < fset.size(); i++) {
274 if (fset.getFeatureAt(i) instanceof DrawableSeqFeature) {
275 FeaturePair sf = (FeaturePair)((DrawableSeqFeature)fset.getFeatureAt(i)).getFeature();
276 boolean found = false;
277
278 for (int k=0; k < newsets.size(); k++) {
279 FeatureSetI tmp1 = (FeatureSetI)newsets.getFeatureAt(k);
280 FeaturePair tmp2 = (FeaturePair)tmp1.getFeatureAt(tmp1.size()-1);
281
282 if (tmp2.getStrand() == sf.getStrand()) {
283 if (tmp2.getStrand() == 1) {
284 if ((Math.abs(tmp2.getHend() - sf.getHstart())) <= gap) {
285 tmp1.addFeature(sf);
286 found = true;
287 }
288 } else if ((Math.abs(tmp2.getHstart() - sf.getHend())) <= gap) {
289 tmp1.addFeature(sf);
290 found = true;
291 }
292
293 }
294 }
295 if (found == false) {
296 FeatureSet newfs = new FeatureSet();
297 newfs.addFeature(sf);
298 newsets.addFeature(newfs);
299 }
300 }
301 }
302 return newsets;
303 }
304 public int _countIntrons(SeqFeatureI sf) {
305 if (sf instanceof FeatureSetI) {
306 FeatureSetI fset = (FeatureSetI)sf;
307 int introns = 0;
308 for (int i=0; i < fset.size()-1; i++) {
309 SeqFeatureI sf1 = fset.getFeatureAt(i);
310 SeqFeatureI sf2 = fset.getFeatureAt(i+1);
311
312 if ((sf2.getStart() - sf1.getEnd()) > 50) {
313 introns++;
314 }
315 }
316 return introns;
317 } else {
318 return 0;
319 }
320 }
321 public Vector makeGeneSets(SeqFeatureI sf) {
322
323 if (sf instanceof FeatureSetI) {
324 FeatureSetI fset = (FeatureSetI)sf;
325 Hashtable ghash = new Hashtable();
326
327 for (int i=0; i < fset.size(); i++) {
328 SeqFeatureI sf2 = fset.getFeatureAt(i);
329 if (ghash.containsKey(sf2.getName())) {
330 FeatureSet tmp = (FeatureSet)ghash.get(sf2.getName());
331 tmp.addFeature(sf2);
332 ghash.put(sf2.getName(),tmp);
333 } else {
334 FeatureSet tmp = new FeatureSet();
335 tmp.addFeature(sf2);
336 ghash.put(sf2.getName(),tmp);
337 }
338 }
339
340 Enumeration e = ghash.keys();
341 FeatureSet newfset = new FeatureSet();
342 while (e.hasMoreElements()) {
343 FeatureSetI sf2 = (FeatureSetI)ghash.get(e.nextElement());
344 newfset.addFeature(sf2);
345
346 }
347 return newfset.getFeatures();
348 } else {
349 return null;
350 }
351 }
352
353
354 // SeqFeatureI methods
355 public int getStrand() {
356 if (size() > 0) {
357 return getFeatureAt(0).getStrand();
358 } else {
359 return 1;
360 }
361 }
362 public String getName() {
363 if (size() > 0) {
364 return getFeatureAt(0).getName();
365 } else {
366 return "SeqFeatureI.NO_NAME";
367 }
368 }
369
370 public String getType() {
371 if (size() > 0) {
372 return getFeatureAt(0).getType();
373 } else {
374 return "SeqFeatureI.NO_TYPE";
375 }
376 }
377 // Internal methods
378 private void _setEnds() {
379 start = 10000000;
380 end = -10000000;
381
382 for (int i=0; i< size(); i++) {
383 if (getFeatureAt(i).getStart() < start) {
384 start = getFeatureAt(i).getStart();
385 }
386 if (getFeatureAt(i).getEnd() > end) {
387 end = getFeatureAt(i).getEnd();
388 }
389 }
390 }
391 }
392