Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
FeatureSettingsTest | 54 | 109 | 9 |
1 | /* | |
2 | * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) | |
3 | * Copyright (C) $$Year-Rel$$ The Jalview Authors | |
4 | * | |
5 | * This file is part of Jalview. | |
6 | * | |
7 | * Jalview is free software: you can redistribute it and/or | |
8 | * modify it under the terms of the GNU General Public License | |
9 | * as published by the Free Software Foundation, either version 3 | |
10 | * of the License, or (at your option) any later version. | |
11 | * | |
12 | * Jalview is distributed in the hope that it will be useful, but | |
13 | * WITHOUT ANY WARRANTY; without even the implied warranty | |
14 | * of MERCHANTABILITY or FITNESS FOR A PARTICULAR | |
15 | * PURPOSE. See the GNU General Public License for more details. | |
16 | * | |
17 | * You should have received a copy of the GNU General Public License | |
18 | * along with Jalview. If not, see <http://www.gnu.org/licenses/>. | |
19 | * The Jalview Authors are detailed in the 'AUTHORS' file. | |
20 | */ | |
21 | package jalview.gui; | |
22 | ||
23 | import static org.testng.Assert.assertEquals; | |
24 | import static org.testng.Assert.assertNull; | |
25 | import static org.testng.Assert.assertTrue; | |
26 | ||
27 | import java.awt.Color; | |
28 | import java.io.File; | |
29 | import java.io.IOException; | |
30 | import java.util.HashMap; | |
31 | ||
32 | import org.testng.annotations.AfterMethod; | |
33 | import org.testng.annotations.BeforeClass; | |
34 | import org.testng.annotations.Test; | |
35 | ||
36 | import jalview.api.FeatureColourI; | |
37 | import jalview.bin.Cache; | |
38 | import jalview.bin.Jalview; | |
39 | import jalview.datamodel.SequenceFeature; | |
40 | import jalview.datamodel.SequenceI; | |
41 | import jalview.datamodel.features.FeatureMatcher; | |
42 | import jalview.datamodel.features.FeatureMatcherSet; | |
43 | import jalview.datamodel.features.FeatureMatcherSetI; | |
44 | import jalview.io.DataSourceType; | |
45 | import jalview.io.FileFormat; | |
46 | import jalview.io.FileFormatI; | |
47 | import jalview.io.FileLoader; | |
48 | import jalview.io.IdentifyFile; | |
49 | import jalview.schemes.FeatureColour; | |
50 | import jalview.schemes.FeatureColourTest; | |
51 | import jalview.util.matcher.Condition; | |
52 | import jalview.viewmodel.seqfeatures.FeatureRendererModel; | |
53 | ||
54 | public class FeatureSettingsTest | |
55 | { | |
56 | 1 | @BeforeClass(alwaysRun = true) |
57 | public static void setUpBeforeClass() throws Exception | |
58 | { | |
59 | /* | |
60 | * use read-only test properties file | |
61 | */ | |
62 | 1 | Cache.loadProperties("test/jalview/io/testProps.jvprops"); |
63 | 1 | Jalview.main(new String[] { "--nonews" }); |
64 | } | |
65 | ||
66 | 3 | @AfterMethod(alwaysRun = true) |
67 | public void tearDown() | |
68 | { | |
69 | 3 | if (Desktop.instance != null) |
70 | 3 | Desktop.instance.closeAll_actionPerformed(null); |
71 | } | |
72 | ||
73 | /** | |
74 | * Test a roundtrip of save and reload of feature colours and filters as XML | |
75 | * | |
76 | * @throws IOException | |
77 | */ | |
78 | 1 | @Test(groups = "Functional") |
79 | public void testSaveLoad() throws IOException | |
80 | { | |
81 | 1 | AlignFrame af = new FileLoader().LoadFileWaitTillLoaded( |
82 | ">Seq1\nACDEFGHIKLM", DataSourceType.PASTE); | |
83 | 1 | SequenceI seq1 = af.getViewport().getAlignment().getSequenceAt(0); |
84 | ||
85 | /* | |
86 | * add some features to the sequence | |
87 | */ | |
88 | 1 | int score = 1; |
89 | 1 | addFeatures(seq1, "type1", score++); |
90 | 1 | addFeatures(seq1, "type2", score++); |
91 | 1 | addFeatures(seq1, "type3", score++); |
92 | 1 | addFeatures(seq1, "type4", score++); |
93 | 1 | addFeatures(seq1, "type5", score++); |
94 | ||
95 | /* | |
96 | * set colour schemes for features | |
97 | */ | |
98 | 1 | FeatureRendererModel fr = af.getFeatureRenderer(); |
99 | ||
100 | // type1: red | |
101 | 1 | fr.setColour("type1", new FeatureColour(Color.red)); |
102 | ||
103 | // type2: by label | |
104 | 1 | FeatureColourI byLabel = new FeatureColour(); |
105 | 1 | byLabel.setColourByLabel(true); |
106 | 1 | fr.setColour("type2", byLabel); |
107 | ||
108 | // type3: by score above threshold | |
109 | 1 | FeatureColourI byScore = new FeatureColour(null, Color.BLACK, |
110 | Color.BLUE, null, 1, 10); | |
111 | 1 | byScore.setAboveThreshold(true); |
112 | 1 | byScore.setThreshold(2f); |
113 | 1 | fr.setColour("type3", byScore); |
114 | ||
115 | // type4: by attribute AF | |
116 | 1 | FeatureColourI byAF = new FeatureColour(); |
117 | 1 | byAF.setColourByLabel(true); |
118 | 1 | byAF.setAttributeName("AF"); |
119 | 1 | fr.setColour("type4", byAF); |
120 | ||
121 | // type5: by attribute CSQ:PolyPhen below threshold | |
122 | 1 | FeatureColourI byPolyPhen = new FeatureColour(null, Color.BLACK, |
123 | Color.BLUE, null, 1, 10); | |
124 | 1 | byPolyPhen.setBelowThreshold(true); |
125 | 1 | byPolyPhen.setThreshold(3f); |
126 | 1 | byPolyPhen.setAttributeName("CSQ", "PolyPhen"); |
127 | 1 | fr.setColour("type5", byPolyPhen); |
128 | ||
129 | /* | |
130 | * set filters for feature types | |
131 | */ | |
132 | ||
133 | // filter type1 features by (label contains "x") | |
134 | 1 | FeatureMatcherSetI filterByX = new FeatureMatcherSet(); |
135 | 1 | filterByX.and(FeatureMatcher.byLabel(Condition.Contains, "x")); |
136 | 1 | fr.setFeatureFilter("type1", filterByX); |
137 | ||
138 | // filter type2 features by (score <= 2.4 and score > 1.1) | |
139 | 1 | FeatureMatcherSetI filterByScore = new FeatureMatcherSet(); |
140 | 1 | filterByScore.and(FeatureMatcher.byScore(Condition.LE, "2.4")); |
141 | 1 | filterByScore.and(FeatureMatcher.byScore(Condition.GT, "1.1")); |
142 | 1 | fr.setFeatureFilter("type2", filterByScore); |
143 | ||
144 | // filter type3 features by (AF contains X OR CSQ:PolyPhen != 0) | |
145 | 1 | FeatureMatcherSetI filterByXY = new FeatureMatcherSet(); |
146 | 1 | filterByXY |
147 | .and(FeatureMatcher.byAttribute(Condition.Contains, "X", "AF")); | |
148 | 1 | filterByXY.or(FeatureMatcher.byAttribute(Condition.NE, "0", "CSQ", |
149 | "PolyPhen")); | |
150 | 1 | fr.setFeatureFilter("type3", filterByXY); |
151 | ||
152 | /* | |
153 | * save colours and filters to an XML file | |
154 | */ | |
155 | 1 | File coloursFile = File.createTempFile("testSaveLoad", ".fc"); |
156 | 1 | coloursFile.deleteOnExit(); |
157 | 1 | FeatureSettings fs = new FeatureSettings(af); |
158 | 1 | fs.save(coloursFile); |
159 | ||
160 | /* | |
161 | * change feature colours and filters | |
162 | */ | |
163 | 1 | FeatureColourI pink = new FeatureColour(Color.pink); |
164 | 1 | fr.setColour("type1", pink); |
165 | 1 | fr.setColour("type2", pink); |
166 | 1 | fr.setColour("type3", pink); |
167 | 1 | fr.setColour("type4", pink); |
168 | 1 | fr.setColour("type5", pink); |
169 | ||
170 | 1 | FeatureMatcherSetI filter2 = new FeatureMatcherSet(); |
171 | 1 | filter2.and(FeatureMatcher.byLabel(Condition.NotContains, "y")); |
172 | 1 | fr.setFeatureFilter("type1", filter2); |
173 | 1 | fr.setFeatureFilter("type2", filter2); |
174 | 1 | fr.setFeatureFilter("type3", filter2); |
175 | 1 | fr.setFeatureFilter("type4", filter2); |
176 | 1 | fr.setFeatureFilter("type5", filter2); |
177 | ||
178 | /* | |
179 | * reload colours and filters from file and verify they are restored | |
180 | */ | |
181 | 1 | fs.load(coloursFile); |
182 | 1 | FeatureColourI fc = fr.getFeatureStyle("type1"); |
183 | 1 | assertTrue(fc.isSimpleColour()); |
184 | 1 | assertEquals(fc.getColour(), Color.red); |
185 | 1 | fc = fr.getFeatureStyle("type2"); |
186 | 1 | assertTrue(fc.isColourByLabel()); |
187 | 1 | fc = fr.getFeatureStyle("type3"); |
188 | 1 | assertTrue(fc.isGraduatedColour()); |
189 | 1 | assertNull(fc.getAttributeName()); |
190 | 1 | assertTrue(fc.isAboveThreshold()); |
191 | 1 | assertEquals(fc.getThreshold(), 2f); |
192 | 1 | fc = fr.getFeatureStyle("type4"); |
193 | 1 | assertTrue(fc.isColourByLabel()); |
194 | 1 | assertTrue(fc.isColourByAttribute()); |
195 | 1 | assertEquals(fc.getAttributeName(), new String[] { "AF" }); |
196 | 1 | fc = fr.getFeatureStyle("type5"); |
197 | 1 | assertTrue(fc.isGraduatedColour()); |
198 | 1 | assertTrue(fc.isColourByAttribute()); |
199 | 1 | assertEquals(fc.getAttributeName(), new String[] { "CSQ", "PolyPhen" }); |
200 | 1 | assertTrue(fc.isBelowThreshold()); |
201 | 1 | assertEquals(fc.getThreshold(), 3f); |
202 | ||
203 | 1 | assertEquals(fr.getFeatureFilter("type1").toStableString(), |
204 | "Label Contains x"); | |
205 | 1 | assertEquals(fr.getFeatureFilter("type2").toStableString(), |
206 | "(Score LE 2.4) AND (Score GT 1.1)"); | |
207 | 1 | assertEquals(fr.getFeatureFilter("type3").toStableString(), |
208 | "(AF Contains X) OR (CSQ:PolyPhen NE 0)"); | |
209 | } | |
210 | ||
211 | /** | |
212 | * Adds two features of the given type to the given sequence, also setting the | |
213 | * score as the value of attribute "AF" and sub-attribute "CSQ:PolyPhen" | |
214 | * | |
215 | * @param seq | |
216 | * @param featureType | |
217 | * @param score | |
218 | */ | |
219 | 5 | private void addFeatures(SequenceI seq, String featureType, int score) |
220 | { | |
221 | 5 | addFeature(seq, featureType, score++); |
222 | 5 | addFeature(seq, featureType, score); |
223 | } | |
224 | ||
225 | 10 | private void addFeature(SequenceI seq, String featureType, int score) |
226 | { | |
227 | 10 | SequenceFeature sf = new SequenceFeature(featureType, "desc", 1, 2, |
228 | score, "grp"); | |
229 | 10 | sf.setValue("AF", score); |
230 | 10 | sf.setValue("CSQ", new HashMap<String, String>() |
231 | { | |
232 | 10 | { |
233 | 10 | put("PolyPhen", Integer.toString(score)); |
234 | } | |
235 | }); | |
236 | 10 | seq.addSequenceFeature(sf); |
237 | } | |
238 | ||
239 | /** | |
240 | * @see FeatureColourTest#testGetDescription() | |
241 | * @throws IOException | |
242 | */ | |
243 | 1 | @Test(groups = "Functional") |
244 | public void testGetColorTooltip() throws IOException | |
245 | { | |
246 | 1 | assertNull(FeatureSettings.getColorTooltip(null, false)); |
247 | ||
248 | /* | |
249 | * simple colour | |
250 | */ | |
251 | 1 | FeatureColourI fc = new FeatureColour(Color.black); |
252 | 1 | String simpleTooltip = "Click to edit, right-click for menu"; |
253 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, true), simpleTooltip); |
254 | 1 | assertNull(FeatureSettings.getColorTooltip(fc, false)); |
255 | ||
256 | /* | |
257 | * graduated colour tooltip includes description of colour | |
258 | */ | |
259 | 1 | fc.setColourByLabel(true); |
260 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, false), |
261 | "<html>By Label</html>"); | |
262 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, true), |
263 | "<html>By Label<br>" + simpleTooltip + "</br></html>"); | |
264 | ||
265 | /* | |
266 | * graduated colour with threshold is html-encoded | |
267 | */ | |
268 | 1 | fc = new FeatureColour(null, Color.red, Color.blue, null, 2f, 10f); |
269 | 1 | fc.setBelowThreshold(true); |
270 | 1 | fc.setThreshold(4f); |
271 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, false), |
272 | "<html>By Score (< 4.0)</html>"); | |
273 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, true), |
274 | "<html>By Score (< 4.0)<br>" + simpleTooltip | |
275 | + "</br></html>"); | |
276 | ||
277 | 1 | fc.setAboveThreshold(true); |
278 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, false), |
279 | "<html>By Score (> 4.0)</html>"); | |
280 | 1 | assertEquals(FeatureSettings.getColorTooltip(fc, true), |
281 | "<html>By Score (> 4.0)<br>" + simpleTooltip | |
282 | + "</br></html>"); | |
283 | } | |
284 | ||
285 | String fsfile = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><ns2:JalviewUserColours schemeName=\"Sequence Features\" xmlns:ns2=\"www.jalview.org/colours\">", | |
286 | fsfile2 = "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<ns2:JalviewUserColours schemeName=\"Sequence Features\" xmlns:ns2=\"www.jalview.org/colours\">"; | |
287 | ||
288 | 1 | @Test(groups = "Functional") |
289 | public void testIdentifyFeatureSettingsFile() throws Exception | |
290 | { | |
291 | 1 | FileFormatI type = new IdentifyFile().identify(fsfile, |
292 | DataSourceType.PASTE); | |
293 | 1 | assertTrue(FileFormat.FeatureSettings == type, |
294 | "Feature settings file was identified as " + type); | |
295 | 1 | type = new IdentifyFile().identify(fsfile2, DataSourceType.PASTE); |
296 | 1 | assertTrue(FileFormat.FeatureSettings == type, |
297 | "Feature settings file with newline was identified as " + type); | |
298 | } | |
299 | } |