JAL-2483 JAL-2481 fixed findAllFeatures to handle null group correctly
[jalview.git] / test / jalview / renderer / seqfeatures / FeatureRendererTest.java
1 package jalview.renderer.seqfeatures;
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.api.AlignViewportI;
8 import jalview.api.FeatureColourI;
9 import jalview.datamodel.SequenceFeature;
10 import jalview.datamodel.SequenceI;
11 import jalview.gui.AlignFrame;
12 import jalview.io.DataSourceType;
13 import jalview.io.FileLoader;
14 import jalview.schemes.FeatureColour;
15
16 import java.awt.Color;
17 import java.util.Arrays;
18 import java.util.List;
19 import java.util.Map;
20
21 import org.testng.annotations.Test;
22
23 public class FeatureRendererTest
24 {
25
26   @Test(groups = "Functional")
27   public void testFindAllFeatures()
28   {
29     String seqData = ">s1\nabcdef\n>s2\nabcdef\n>s3\nabcdef\n>s4\nabcdef\n";
30     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
31             DataSourceType.PASTE);
32     AlignViewportI av = af.getViewport();
33     FeatureRenderer fr = new FeatureRenderer(av);
34
35     /*
36      * with no features
37      */
38     fr.findAllFeatures(true);
39     assertTrue(fr.getRenderOrder().isEmpty());
40     assertTrue(fr.getFeatureGroups().isEmpty());
41
42     List<SequenceI> seqs = av.getAlignment().getSequences();
43
44     // add a non-positional feature - should be ignored by FeatureRenderer
45     SequenceFeature sf1 = new SequenceFeature("Type", "Desc", 0, 0, 1f,
46             "Group");
47     seqs.get(0).addSequenceFeature(sf1);
48     fr.findAllFeatures(true);
49     // ? bug - types and groups added for non-positional features
50     List<String> types = fr.getRenderOrder();
51     List<String> groups = fr.getFeatureGroups();
52     assertEquals(types.size(), 0);
53     assertFalse(types.contains("Type"));
54     assertEquals(groups.size(), 0);
55     assertFalse(groups.contains("Group"));
56
57     // add some positional features
58     seqs.get(1).addSequenceFeature(
59             new SequenceFeature("Pfam", "Desc", 5, 9, 1f, "PfamGroup"));
60     seqs.get(2).addSequenceFeature(
61             new SequenceFeature("Pfam", "Desc", 14, 22, 2f, "RfamGroup"));
62     // bug in findAllFeatures - group not checked for a known feature type
63     seqs.get(2).addSequenceFeature(
64             new SequenceFeature("Rfam", "Desc", 5, 9, Float.NaN,
65                     "RfamGroup"));
66     // existing feature type with null group
67     seqs.get(3).addSequenceFeature(
68             new SequenceFeature("Rfam", "Desc", 5, 9, Float.NaN, null));
69     // new feature type with null group
70     seqs.get(3).addSequenceFeature(
71             new SequenceFeature("Scop", "Desc", 5, 9, Float.NaN, null));
72     // null value for type produces NullPointerException
73     fr.findAllFeatures(true);
74     types = fr.getRenderOrder();
75     groups = fr.getFeatureGroups();
76     assertEquals(types.size(), 3);
77     assertFalse(types.contains("Type"));
78     assertTrue(types.contains("Pfam"));
79     assertTrue(types.contains("Rfam"));
80     assertTrue(types.contains("Scop"));
81     assertEquals(groups.size(), 2);
82     assertFalse(groups.contains("Group"));
83     assertTrue(groups.contains("PfamGroup"));
84     assertTrue(groups.contains("RfamGroup"));
85     assertFalse(groups.contains(null)); // null group is ignored
86
87     /*
88      * check min-max values
89      */
90     Map<String, float[][]> minMax = fr.getMinMax();
91     assertEquals(minMax.size(), 1); // non-positional and NaN not stored
92     assertEquals(minMax.get("Pfam")[0][0], 1f); // positional min
93     assertEquals(minMax.get("Pfam")[0][1], 2f); // positional max
94
95     // increase max for Pfam, add scores for Rfam
96     seqs.get(0).addSequenceFeature(
97             new SequenceFeature("Pfam", "Desc", 14, 22, 8f, "RfamGroup"));
98     seqs.get(1).addSequenceFeature(
99             new SequenceFeature("Rfam", "Desc", 5, 9, 6f, "RfamGroup"));
100     fr.findAllFeatures(true);
101     // note minMax is not a defensive copy, shouldn't expose this
102     assertEquals(minMax.size(), 2);
103     assertEquals(minMax.get("Pfam")[0][0], 1f);
104     assertEquals(minMax.get("Pfam")[0][1], 8f);
105     assertEquals(minMax.get("Rfam")[0][0], 6f);
106     assertEquals(minMax.get("Rfam")[0][1], 6f);
107
108     /*
109      * check render order (last is on top)
110      */
111     List<String> renderOrder = fr.getRenderOrder();
112     assertEquals(renderOrder, Arrays.asList("Scop", "Rfam", "Pfam"));
113
114     /*
115      * change render order (todo: an easier way)
116      * nb here last comes first in the data array
117      */
118     Object[][] data = new Object[3][];
119     FeatureColourI colour = new FeatureColour(Color.RED);
120     data[0] = new Object[] { "Rfam", colour, true };
121     data[1] = new Object[] { "Pfam", colour, false };
122     data[2] = new Object[] { "Scop", colour, false };
123     fr.setFeaturePriority(data);
124     assertEquals(fr.getRenderOrder(), Arrays.asList("Scop", "Pfam", "Rfam"));
125     assertEquals(fr.getDisplayedFeatureTypes(), Arrays.asList("Rfam"));
126
127     /*
128      * add a new feature type: should go on top of render order as visible,
129      * other feature ordering and visibility should be unchanged
130      */
131     seqs.get(2).addSequenceFeature(
132             new SequenceFeature("Metal", "Desc", 14, 22, 8f, "MetalGroup"));
133     fr.findAllFeatures(true);
134     assertEquals(fr.getRenderOrder(),
135             Arrays.asList("Scop", "Pfam", "Rfam", "Metal"));
136     assertEquals(fr.getDisplayedFeatureTypes(),
137             Arrays.asList("Rfam", "Metal"));
138   }
139
140   @Test(groups = "Functional")
141   public void testFindFeaturesAtRes()
142   {
143     String seqData = ">s1\nabcdefghijklmnopqrstuvwxyz\n";
144     AlignFrame af = new FileLoader().LoadFileWaitTillLoaded(seqData,
145             DataSourceType.PASTE);
146     AlignViewportI av = af.getViewport();
147     FeatureRenderer fr = new FeatureRenderer(av);
148     SequenceI seq = av.getAlignment().getSequenceAt(0);
149
150     /*
151      * with no features
152      */
153     List<SequenceFeature> features = fr.findFeaturesAtRes(seq, 3);
154     assertTrue(features.isEmpty());
155
156     /*
157      * add features
158      */
159     SequenceFeature sf1 = new SequenceFeature("Type1", "Desc", 0, 0, 1f,
160             "Group"); // non-positional
161     seq.addSequenceFeature(sf1);
162     SequenceFeature sf2 = new SequenceFeature("Type2", "Desc", 5, 15, 1f,
163             "Group1");
164     seq.addSequenceFeature(sf2);
165     SequenceFeature sf3 = new SequenceFeature("Type3", "Desc", 5, 15, 1f,
166             "Group2");
167     seq.addSequenceFeature(sf3);
168     SequenceFeature sf4 = new SequenceFeature("Type3", "Desc", 5, 15, 1f,
169             null); // null group is always treated as visible
170     seq.addSequenceFeature(sf4);
171
172     /*
173      * add contact features
174      */
175     SequenceFeature sf5 = new SequenceFeature("Disulphide Bond", "Desc", 4,
176             12, 1f, "Group1");
177     seq.addSequenceFeature(sf5);
178     SequenceFeature sf6 = new SequenceFeature("Disulphide Bond", "Desc", 4,
179             12, 1f, "Group2");
180     seq.addSequenceFeature(sf6);
181     SequenceFeature sf7 = new SequenceFeature("Disulphide Bond", "Desc", 4,
182             12, 1f, null);
183     seq.addSequenceFeature(sf7);
184
185     /*
186      * let feature renderer discover features (and make visible)
187      */
188     fr.findAllFeatures(true);
189     features = fr.findFeaturesAtRes(seq, 12); // all positional
190     assertEquals(features.size(), 6);
191     assertTrue(features.contains(sf2));
192     assertTrue(features.contains(sf3));
193     assertTrue(features.contains(sf4));
194     assertTrue(features.contains(sf5));
195     assertTrue(features.contains(sf6));
196     assertTrue(features.contains(sf7));
197
198     /*
199      * at a non-contact position
200      */
201     features = fr.findFeaturesAtRes(seq, 11);
202     assertEquals(features.size(), 3);
203     assertTrue(features.contains(sf2));
204     assertTrue(features.contains(sf3));
205     assertTrue(features.contains(sf4));
206
207     /*
208      * make "Type2" not displayed
209      */
210     Object[][] data = new Object[4][];
211     FeatureColourI colour = new FeatureColour(Color.RED);
212     data[0] = new Object[] { "Type1", colour, true };
213     data[1] = new Object[] { "Type2", colour, false };
214     data[2] = new Object[] { "Type3", colour, true };
215     data[3] = new Object[] { "Disulphide Bond", colour, true };
216     fr.setFeaturePriority(data);
217     features = fr.findFeaturesAtRes(seq, 12);
218     assertEquals(features.size(), 5); // no sf2
219     assertTrue(features.contains(sf3));
220     assertTrue(features.contains(sf4));
221     assertTrue(features.contains(sf5));
222     assertTrue(features.contains(sf6));
223     assertTrue(features.contains(sf7));
224
225     /*
226      * make "Group2" not displayed
227      */
228     fr.setGroupVisibility("Group2", false);
229     features = fr.findFeaturesAtRes(seq, 12);
230     assertEquals(features.size(), 3); // no sf2, sf3, sf6
231     assertTrue(features.contains(sf4));
232     assertTrue(features.contains(sf5));
233     assertTrue(features.contains(sf7));
234   }
235 }