JAL-2446 find feature types for one or more groups (vararg)
[jalview.git] / test / jalview / datamodel / features / SequenceFeaturesTest.java
1 package jalview.datamodel.features;
2
3 import static org.testng.Assert.assertEquals;
4 import static org.testng.Assert.assertFalse;
5 import static org.testng.Assert.assertTrue;
6
7 import jalview.datamodel.SequenceFeature;
8
9 import java.util.List;
10 import java.util.Set;
11
12 import org.testng.annotations.Test;
13
14 public class SequenceFeaturesTest
15 {
16   @Test(groups = "Functional")
17   public void testGetFeatures()
18   {
19     SequenceFeatures store = new SequenceFeatures();
20     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
21             Float.NaN, null);
22     store.add(sf1);
23     // same range, different description
24     SequenceFeature sf2 = new SequenceFeature("Metal", "desc2", 10, 20,
25             Float.NaN, null);
26     store.add(sf2);
27     // discontiguous range
28     SequenceFeature sf3 = new SequenceFeature("Metal", "desc", 30, 40,
29             Float.NaN, null);
30     store.add(sf3);
31     // overlapping range
32     SequenceFeature sf4 = new SequenceFeature("Metal", "desc", 15, 35,
33             Float.NaN, null);
34     store.add(sf4);
35     // enclosing range
36     SequenceFeature sf5 = new SequenceFeature("Metal", "desc", 5, 50,
37             Float.NaN, null);
38     store.add(sf5);
39     // non-positional feature
40     SequenceFeature sf6 = new SequenceFeature("Metal", "desc", 0, 0,
41             Float.NaN, null);
42     store.add(sf6);
43     // contact feature
44     SequenceFeature sf7 = new SequenceFeature("Disulphide bond", "desc",
45             18, 45, Float.NaN, null);
46     store.add(sf7);
47     // different feature type
48     SequenceFeature sf8 = new SequenceFeature("Pfam", "desc", 30, 40,
49             Float.NaN, null);
50     store.add(sf8);
51     SequenceFeature sf9 = new SequenceFeature("Pfam", "desc", 15, 35,
52             Float.NaN, null);
53     store.add(sf9);
54
55     /*
56      * get all features
57      */
58     List<SequenceFeature> features = store.getFeatures();
59     assertEquals(features.size(), 9);
60     assertTrue(features.contains(sf1));
61     assertTrue(features.contains(sf2));
62     assertTrue(features.contains(sf3));
63     assertTrue(features.contains(sf4));
64     assertTrue(features.contains(sf5));
65     assertTrue(features.contains(sf6));
66     assertTrue(features.contains(sf7));
67     assertTrue(features.contains(sf8));
68     assertTrue(features.contains(sf9));
69
70     /*
71      * get features by type
72      */
73     assertTrue(store.getFeatures(null).isEmpty());
74     assertTrue(store.getFeatures("Cath").isEmpty());
75     assertTrue(store.getFeatures("METAL").isEmpty());
76
77     features = store.getFeatures("Metal");
78     assertEquals(features.size(), 6);
79     assertTrue(features.contains(sf1));
80     assertTrue(features.contains(sf2));
81     assertTrue(features.contains(sf3));
82     assertTrue(features.contains(sf4));
83     assertTrue(features.contains(sf5));
84     assertTrue(features.contains(sf6));
85
86     features = store.getFeatures("Disulphide bond");
87     assertEquals(features.size(), 1);
88     assertTrue(features.contains(sf7));
89
90     features = store.getFeatures("Pfam");
91     assertEquals(features.size(), 2);
92     assertTrue(features.contains(sf8));
93     assertTrue(features.contains(sf9));
94   }
95
96   @Test(groups = "Functional")
97   public void testGetContactFeatures()
98   {
99     SequenceFeatures store = new SequenceFeatures();
100     // non-contact
101     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
102             Float.NaN, null);
103     store.add(sf1);
104     // non-positional
105     SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
106             Float.NaN, null);
107     store.add(sf2);
108     // contact feature
109     SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
110             18, 45, Float.NaN, null);
111     store.add(sf3);
112     // repeat for different feature type
113     SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
114             Float.NaN, null);
115     store.add(sf4);
116     SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
117             Float.NaN, null);
118     store.add(sf5);
119     SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
120             45, Float.NaN, null);
121     store.add(sf6);
122   
123     /*
124      * get all contact features
125      */
126     List<SequenceFeature> features = store.getContactFeatures();
127     assertEquals(features.size(), 2);
128     assertTrue(features.contains(sf3));
129     assertTrue(features.contains(sf6));
130   
131     /*
132      * get contact features by type
133      */
134     assertTrue(store.getContactFeatures(null).isEmpty());
135     assertTrue(store.getContactFeatures("Cath").isEmpty());
136     assertTrue(store.getContactFeatures("Pfam").isEmpty());
137     assertTrue(store.getContactFeatures("DISULPHIDE BOND").isEmpty());
138   
139     features = store.getContactFeatures("Disulphide bond");
140     assertEquals(features.size(), 1);
141     assertTrue(features.contains(sf3));
142   
143     features = store.getContactFeatures("Disulfide bond");
144     assertEquals(features.size(), 1);
145     assertTrue(features.contains(sf6));
146   }
147
148   @Test(groups = "Functional")
149   public void testGetNonPositionalFeatures()
150   {
151     SequenceFeatures store = new SequenceFeatures();
152     // positional
153     SequenceFeature sf1 = new SequenceFeature("Metal", "desc", 10, 20,
154             Float.NaN, null);
155     store.add(sf1);
156     // non-positional
157     SequenceFeature sf2 = new SequenceFeature("Metal", "desc", 0, 0,
158             Float.NaN, null);
159     store.add(sf2);
160     // contact feature
161     SequenceFeature sf3 = new SequenceFeature("Disulphide bond", "desc",
162             18, 45, Float.NaN, null);
163     store.add(sf3);
164     // repeat for different feature type
165     SequenceFeature sf4 = new SequenceFeature("Pfam", "desc", 10, 20,
166             Float.NaN, null);
167     store.add(sf4);
168     SequenceFeature sf5 = new SequenceFeature("Pfam", "desc", 0, 0,
169             Float.NaN, null);
170     store.add(sf5);
171     SequenceFeature sf6 = new SequenceFeature("Disulfide bond", "desc", 18,
172             45, Float.NaN, null);
173     store.add(sf6);
174     // one more non-positional, different description
175     SequenceFeature sf7 = new SequenceFeature("Pfam", "desc2", 0, 0,
176             Float.NaN, null);
177     store.add(sf7);
178   
179     /*
180      * get all non-positional features
181      */
182     List<SequenceFeature> features = store.getNonPositionalFeatures();
183     assertEquals(features.size(), 3);
184     assertTrue(features.contains(sf2));
185     assertTrue(features.contains(sf5));
186     assertTrue(features.contains(sf7));
187   
188     /*
189      * get non-positional features by type
190      */
191     assertTrue(store.getNonPositionalFeatures(null).isEmpty());
192     assertTrue(store.getNonPositionalFeatures("Cath").isEmpty());
193     assertTrue(store.getNonPositionalFeatures("PFAM").isEmpty());
194   
195     features = store.getNonPositionalFeatures("Metal");
196     assertEquals(features.size(), 1);
197     assertTrue(features.contains(sf2));
198   
199     features = store.getNonPositionalFeatures("Pfam");
200     assertEquals(features.size(), 2);
201     assertTrue(features.contains(sf5));
202     assertTrue(features.contains(sf7));
203   }
204
205   /**
206    * Helper method to add a feature of no particular type
207    * 
208    * @param sf
209    * @param type
210    * @param from
211    * @param to
212    * @return
213    */
214   SequenceFeature addFeature(SequenceFeatures sf, String type, int from,
215           int to)
216   {
217     SequenceFeature sf1 = new SequenceFeature(type, "", from, to,
218             Float.NaN,
219             null);
220     sf.add(sf1);
221     return sf1;
222   }
223
224   @Test(groups = "Functional")
225   public void testFindFeatures()
226   {
227     SequenceFeatures sf = new SequenceFeatures();
228     SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
229     SequenceFeature sf2 = addFeature(sf, "Pfam", 1, 15);
230     SequenceFeature sf3 = addFeature(sf, "Pfam", 20, 30);
231     SequenceFeature sf4 = addFeature(sf, "Pfam", 40, 100);
232     SequenceFeature sf5 = addFeature(sf, "Pfam", 60, 100);
233     SequenceFeature sf6 = addFeature(sf, "Pfam", 70, 70);
234     SequenceFeature sf7 = addFeature(sf, "Cath", 10, 50);
235     SequenceFeature sf8 = addFeature(sf, "Cath", 1, 15);
236     SequenceFeature sf9 = addFeature(sf, "Cath", 20, 30);
237     SequenceFeature sf10 = addFeature(sf, "Cath", 40, 100);
238     SequenceFeature sf11 = addFeature(sf, "Cath", 60, 100);
239     SequenceFeature sf12 = addFeature(sf, "Cath", 70, 70);
240     // null type is weird but possible:
241     SequenceFeature sf13 = addFeature(sf, null, 5, 12);
242   
243     List<SequenceFeature> overlaps = sf.findFeatures("Pfam", 200, 200);
244     assertTrue(overlaps.isEmpty());
245   
246     overlaps = sf.findFeatures("Pfam", 1, 9);
247     assertEquals(overlaps.size(), 1);
248     assertTrue(overlaps.contains(sf2));
249   
250     overlaps = sf.findFeatures("Pfam", 5, 18);
251     assertEquals(overlaps.size(), 2);
252     assertTrue(overlaps.contains(sf1));
253     assertTrue(overlaps.contains(sf2));
254   
255     overlaps = sf.findFeatures("Pfam", 30, 40);
256     assertEquals(overlaps.size(), 3);
257     assertTrue(overlaps.contains(sf1));
258     assertTrue(overlaps.contains(sf3));
259     assertTrue(overlaps.contains(sf4));
260   
261     overlaps = sf.findFeatures("Pfam", 80, 90);
262     assertEquals(overlaps.size(), 2);
263     assertTrue(overlaps.contains(sf4));
264     assertTrue(overlaps.contains(sf5));
265   
266     overlaps = sf.findFeatures("Pfam", 68, 70);
267     assertEquals(overlaps.size(), 3);
268     assertTrue(overlaps.contains(sf4));
269     assertTrue(overlaps.contains(sf5));
270     assertTrue(overlaps.contains(sf6));
271
272     overlaps = sf.findFeatures("Cath", 16, 69);
273     assertEquals(overlaps.size(), 4);
274     assertTrue(overlaps.contains(sf7));
275     assertFalse(overlaps.contains(sf8));
276     assertTrue(overlaps.contains(sf9));
277     assertTrue(overlaps.contains(sf10));
278     assertTrue(overlaps.contains(sf11));
279     assertFalse(overlaps.contains(sf12));
280
281     assertTrue(sf.findFeatures("Metal", 0, 1000).isEmpty());
282
283     overlaps = sf.findFeatures(null, 7, 7);
284     assertEquals(overlaps.size(), 1);
285     assertTrue(overlaps.contains(sf13));
286   }
287
288   @Test(groups = "Functional")
289   public void testDelete()
290   {
291     SequenceFeatures sf = new SequenceFeatures();
292     SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
293     assertTrue(sf.getFeatures().contains(sf1));
294
295     assertFalse(sf.delete(null));
296     SequenceFeature sf2 = new SequenceFeature("Cath", "", 10, 15, 0f, null);
297     assertFalse(sf.delete(sf2)); // not added, can't delete it
298     assertTrue(sf.delete(sf1));
299     assertTrue(sf.getFeatures().isEmpty());
300   }
301
302   @Test(groups = "Functional")
303   public void testHasFeatures()
304   {
305     SequenceFeatures sf = new SequenceFeatures();
306     assertFalse(sf.hasFeatures());
307
308     SequenceFeature sf1 = addFeature(sf, "Pfam", 10, 50);
309     assertTrue(sf.hasFeatures());
310
311     sf.delete(sf1);
312     assertFalse(sf.hasFeatures());
313   }
314
315   @Test(groups = "Functional")
316   public void testGetFeatureGroups()
317   {
318     SequenceFeatures sf = new SequenceFeatures();
319     assertTrue(sf.getFeatureGroups().isEmpty());
320
321     SequenceFeature sf1 = new SequenceFeature("Pfam", "Desc", 10, 50, 0f,
322             "PfamGroup");
323     sf.add(sf1);
324     Set<String> groups = sf.getFeatureGroups();
325     assertEquals(groups.size(), 1);
326     assertTrue(groups.contains("PfamGroup"));
327
328     SequenceFeature sf2 = new SequenceFeature("Cath", "Desc", 10, 50, 0f,
329             null);
330     sf.add(sf2);
331     groups = sf.getFeatureGroups();
332     assertEquals(groups.size(), 2);
333     assertTrue(groups.contains("PfamGroup"));
334     assertTrue(groups.contains(null));
335
336     sf.delete(sf1);
337     sf.delete(sf2);
338     assertTrue(sf.getFeatureGroups().isEmpty());
339
340     SequenceFeature sf3 = new SequenceFeature("CDS", "", 10, 50, 0f,
341             "Ensembl");
342     sf.add(sf3);
343     SequenceFeature sf4 = new SequenceFeature("exon", "", 10, 50, 0f,
344             "Ensembl");
345     sf.add(sf4);
346     groups = sf.getFeatureGroups();
347     assertEquals(groups.size(), 1);
348     assertTrue(groups.contains("Ensembl"));
349
350     /*
351      * delete last Ensembl group feature from CDS features
352      * but still have one in exon features
353      */
354     sf.delete(sf3);
355     groups = sf.getFeatureGroups();
356     assertEquals(groups.size(), 1);
357     assertTrue(groups.contains("Ensembl"));
358   }
359
360   @Test(groups = "Functional")
361   public void testGetFeatureTypesForGroups()
362   {
363     SequenceFeatures sf = new SequenceFeatures();
364     assertTrue(sf.getFeatureTypesForGroups((String) null).isEmpty());
365   
366     /*
367      * add feature with group = "Uniprot", type = "helix"
368      */
369     String groupUniprot = "Uniprot";
370     SequenceFeature sf1 = new SequenceFeature("helix", "Desc", 10, 50, 0f,
371             groupUniprot);
372     sf.add(sf1);
373     Set<String> groups = sf.getFeatureTypesForGroups(groupUniprot);
374     assertEquals(groups.size(), 1);
375     assertTrue(groups.contains("helix"));
376     assertTrue(sf.getFeatureTypesForGroups((String) null).isEmpty());
377   
378     /*
379      * add feature with group = "Uniprot", type = "strand"
380      */
381     SequenceFeature sf2 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
382             groupUniprot);
383     sf.add(sf2);
384     groups = sf.getFeatureTypesForGroups(groupUniprot);
385     assertEquals(groups.size(), 2);
386     assertTrue(groups.contains("helix"));
387     assertTrue(groups.contains("strand"));
388
389     /*
390      * delete the "strand" Uniprot feature - still have "helix"
391      */
392     sf.delete(sf2);
393     groups = sf.getFeatureTypesForGroups(groupUniprot);
394     assertEquals(groups.size(), 1);
395     assertTrue(groups.contains("helix"));
396
397     /*
398      * delete the "helix" Uniprot feature - none left
399      */
400     sf.delete(sf1);
401     assertTrue(sf.getFeatureTypesForGroups(groupUniprot).isEmpty());
402
403     /*
404      * add some null group features
405      */
406     SequenceFeature sf3 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
407             null);
408     sf.add(sf3);
409     SequenceFeature sf4 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
410             null);
411     sf.add(sf4);
412     groups = sf.getFeatureTypesForGroups((String) null);
413     assertEquals(groups.size(), 2);
414     assertTrue(groups.contains("strand"));
415     assertTrue(groups.contains("turn"));
416
417     /*
418      * add strand/Cath  and turn/Scop and query for one or both groups
419      * (find feature types for groups selected in Feature Settings)
420      */
421     SequenceFeature sf5 = new SequenceFeature("strand", "Desc", 10, 50, 0f,
422             "Cath");
423     sf.add(sf5);
424     SequenceFeature sf6 = new SequenceFeature("turn", "Desc", 10, 50, 0f,
425             "Scop");
426     sf.add(sf6);
427     groups = sf.getFeatureTypesForGroups("Cath");
428     assertEquals(groups.size(), 1);
429     assertTrue(groups.contains("strand"));
430     groups = sf.getFeatureTypesForGroups("Scop");
431     assertEquals(groups.size(), 1);
432     assertTrue(groups.contains("turn"));
433     groups = sf.getFeatureTypesForGroups("Cath", "Scop");
434     assertEquals(groups.size(), 2);
435     assertTrue(groups.contains("turn"));
436     assertTrue(groups.contains("strand"));
437     // alternative vararg syntax
438     groups = sf.getFeatureTypesForGroups(new String[] { "Cath", "Scop" });
439     assertEquals(groups.size(), 2);
440     assertTrue(groups.contains("turn"));
441     assertTrue(groups.contains("strand"));
442   }
443 }