Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
ResidueShaderTest | 47 | 124 | 23 |
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.renderer; | |
22 | ||
23 | import static org.testng.AssertJUnit.assertEquals; | |
24 | import static org.testng.AssertJUnit.assertFalse; | |
25 | import static org.testng.AssertJUnit.assertTrue; | |
26 | ||
27 | import jalview.analysis.Conservation; | |
28 | import jalview.datamodel.Profile; | |
29 | import jalview.datamodel.ProfileI; | |
30 | import jalview.datamodel.Profiles; | |
31 | import jalview.datamodel.ProfilesI; | |
32 | import jalview.datamodel.ResidueCount; | |
33 | import jalview.datamodel.SecondaryStructureCount; | |
34 | import jalview.datamodel.Sequence; | |
35 | import jalview.datamodel.SequenceI; | |
36 | import jalview.schemes.ColourSchemeI; | |
37 | import jalview.schemes.PIDColourScheme; | |
38 | import jalview.schemes.ResidueProperties; | |
39 | import jalview.schemes.UserColourScheme; | |
40 | import jalview.schemes.ZappoColourScheme; | |
41 | ||
42 | import java.awt.Color; | |
43 | import java.util.Collections; | |
44 | ||
45 | import org.testng.annotations.Test; | |
46 | ||
47 | public class ResidueShaderTest | |
48 | { | |
49 | ||
50 | 1 | @Test(groups = "Functional") |
51 | public void testAboveThreshold() | |
52 | { | |
53 | /* | |
54 | * make up profiles for this alignment: | |
55 | * AR-Q | |
56 | * AR-- | |
57 | * SR-T | |
58 | * SR-T | |
59 | */ | |
60 | 1 | ProfileI[] profiles = new ProfileI[4]; |
61 | 1 | profiles[0] = new Profile(4, 0, 2, "AS"); |
62 | 1 | profiles[1] = new Profile(4, 0, 4, "R"); |
63 | 1 | profiles[2] = new Profile(4, 4, 0, ""); |
64 | 1 | profiles[3] = new Profile(4, 1, 2, "T"); |
65 | 1 | ResidueShader ccs = new ResidueShader(new PIDColourScheme()); |
66 | 1 | ccs.setConsensus(new Profiles(profiles)); |
67 | ||
68 | /* | |
69 | * no threshold | |
70 | */ | |
71 | 1 | ccs.setThreshold(0, true); |
72 | 1 | assertTrue(ccs.aboveThreshold('a', 0)); |
73 | 1 | assertTrue(ccs.aboveThreshold('S', 0)); |
74 | 1 | assertTrue(ccs.aboveThreshold('W', 0)); |
75 | 1 | assertTrue(ccs.aboveThreshold('R', 1)); |
76 | 1 | assertTrue(ccs.aboveThreshold('W', 2)); |
77 | 1 | assertTrue(ccs.aboveThreshold('t', 3)); |
78 | 1 | assertTrue(ccs.aboveThreshold('Q', 3)); |
79 | ||
80 | /* | |
81 | * with threshold, include gaps | |
82 | */ | |
83 | 1 | ccs.setThreshold(60, false); |
84 | 1 | assertFalse(ccs.aboveThreshold('a', 0)); |
85 | 1 | assertFalse(ccs.aboveThreshold('S', 0)); |
86 | 1 | assertTrue(ccs.aboveThreshold('R', 1)); |
87 | 1 | assertFalse(ccs.aboveThreshold('W', 2)); |
88 | 1 | assertFalse(ccs.aboveThreshold('t', 3)); // 50% < 60% |
89 | ||
90 | /* | |
91 | * with threshold, ignore gaps | |
92 | */ | |
93 | 1 | ccs.setThreshold(60, true); |
94 | 1 | assertFalse(ccs.aboveThreshold('a', 0)); |
95 | 1 | assertFalse(ccs.aboveThreshold('S', 0)); |
96 | 1 | assertTrue(ccs.aboveThreshold('R', 1)); |
97 | 1 | assertFalse(ccs.aboveThreshold('W', 2)); |
98 | 1 | assertTrue(ccs.aboveThreshold('t', 3)); // 67% > 60% |
99 | } | |
100 | ||
101 | /** | |
102 | * Test colour bleaching based on conservation score and conservation slider. | |
103 | * Scores of 10 or 11 should leave colours unchanged. Gap is always white. | |
104 | */ | |
105 | 1 | @Test(groups = "Functional") |
106 | public void testApplyConservation() | |
107 | { | |
108 | 1 | ResidueShader ccs = new ResidueShader(new PIDColourScheme()); |
109 | ||
110 | // no conservation present - no fading | |
111 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 12)); |
112 | ||
113 | /* | |
114 | * stub Conservation to return a given consensus string | |
115 | */ | |
116 | 1 | final String consSequence = "0123456789+*-"; |
117 | 1 | Conservation cons = new Conservation(null, |
118 | Collections.<SequenceI> emptyList(), 0, 0) | |
119 | { | |
120 | 1 | @Override |
121 | public SequenceI getConsSequence() | |
122 | { | |
123 | 1 | return new Sequence("seq", consSequence); |
124 | } | |
125 | }; | |
126 | 1 | ccs.setConservation(cons); |
127 | ||
128 | // column out of range: | |
129 | 1 | assertEquals(Color.RED, |
130 | ccs.applyConservation(Color.RED, consSequence.length())); | |
131 | ||
132 | /* | |
133 | * with 100% threshold, 'fade factor' is | |
134 | * (11-score)/10 * 100/20 = (11-score)/2 | |
135 | * which is >= 1 for all scores i.e. all fade to white except +, * | |
136 | */ | |
137 | 1 | ccs.setConservationInc(100); |
138 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 0)); |
139 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 1)); |
140 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 2)); |
141 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 3)); |
142 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 4)); |
143 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 5)); |
144 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 6)); |
145 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 7)); |
146 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 8)); |
147 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 9)); |
148 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 10)); |
149 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 11)); |
150 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 12)); |
151 | ||
152 | /* | |
153 | * with 0% threshold, there should be no fading | |
154 | */ | |
155 | 1 | ccs.setConservationInc(0); |
156 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 0)); |
157 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 1)); |
158 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 2)); |
159 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 3)); |
160 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 4)); |
161 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 5)); |
162 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 6)); |
163 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 7)); |
164 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 8)); |
165 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 9)); |
166 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 10)); |
167 | 1 | assertEquals(Color.RED, ccs.applyConservation(Color.RED, 11)); |
168 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(Color.RED, 12)); // gap |
169 | ||
170 | /* | |
171 | * with 40% threshold, 'fade factor' is | |
172 | * (11-score)/10 * 40/20 = (11-score)/5 | |
173 | * which is {>1, >1, >1, >1, >1, >1, 1, 0.8, 0.6, 0.4} for score 0-9 | |
174 | * e.g. score 7 colour fades 80% of the way to white (255, 255, 255) | |
175 | */ | |
176 | 1 | ccs.setConservationInc(40); |
177 | 1 | Color colour = new Color(155, 105, 55); |
178 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 0)); |
179 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 1)); |
180 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 2)); |
181 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 3)); |
182 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 4)); |
183 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 5)); |
184 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 6)); |
185 | 1 | assertEquals(new Color(235, 225, 215), |
186 | ccs.applyConservation(colour, 7)); | |
187 | 1 | assertEquals(new Color(215, 195, 175), |
188 | ccs.applyConservation(colour, 8)); | |
189 | 1 | assertEquals(new Color(195, 165, 135), |
190 | ccs.applyConservation(colour, 9)); | |
191 | 1 | assertEquals(colour, ccs.applyConservation(colour, 10)); |
192 | 1 | assertEquals(colour, ccs.applyConservation(colour, 11)); |
193 | 1 | assertEquals(Color.WHITE, ccs.applyConservation(colour, 12)); |
194 | } | |
195 | ||
196 | 1 | @Test(groups = "Functional") |
197 | public void testFindColour_gapColour() | |
198 | { | |
199 | /* | |
200 | * normally, a gap is coloured white | |
201 | */ | |
202 | 1 | ResidueShader rs = new ResidueShader(new ZappoColourScheme()); |
203 | 1 | assertEquals(Color.white, rs.findColour(' ', 7, null)); |
204 | ||
205 | /* | |
206 | * a User Colour Scheme may specify a bespoke gap colour | |
207 | */ | |
208 | 1 | Color[] colours = new Color[ResidueProperties.maxProteinIndex + 1]; |
209 | 1 | colours[5] = Color.blue; // Q colour |
210 | 1 | colours[23] = Color.red; // gap colour |
211 | 1 | ColourSchemeI cs = new UserColourScheme(colours); |
212 | 1 | rs = new ResidueShader(cs); |
213 | ||
214 | 1 | assertEquals(Color.red, rs.findColour(' ', 7, null)); |
215 | 1 | assertEquals(Color.blue, rs.findColour('Q', 7, null)); |
216 | ||
217 | /* | |
218 | * stub Conservation to return a given consensus string | |
219 | */ | |
220 | 1 | final String consSequence = "0123456789+*-"; |
221 | 1 | Conservation cons = new Conservation(null, |
222 | Collections.<SequenceI> emptyList(), 0, 0) | |
223 | { | |
224 | 1 | @Override |
225 | public SequenceI getConsSequence() | |
226 | { | |
227 | 1 | return new Sequence("seq", consSequence); |
228 | } | |
229 | }; | |
230 | 1 | rs.setConservation(cons); |
231 | ||
232 | /* | |
233 | * with 0% threshold, there should be no fading | |
234 | */ | |
235 | 1 | rs.setConservationInc(0); |
236 | 1 | assertEquals(Color.red, rs.findColour(' ', 7, null)); |
237 | 1 | assertEquals(Color.blue, rs.findColour('Q', 7, null)); |
238 | ||
239 | /* | |
240 | * with 40% threshold, 'fade factor' is | |
241 | * (11-score)/10 * 40/20 = (11-score)/5 | |
242 | * so position 7, score 7 fades 80% of the way to white (255, 255, 255) | |
243 | */ | |
244 | 1 | rs.setConservationInc(40); |
245 | ||
246 | /* | |
247 | * gap colour is unchanged for Conservation | |
248 | */ | |
249 | 1 | assertEquals(Color.red, rs.findColour(' ', 7, null)); |
250 | 1 | assertEquals(Color.red, rs.findColour('-', 7, null)); |
251 | 1 | assertEquals(Color.red, rs.findColour('.', 7, null)); |
252 | ||
253 | /* | |
254 | * residue colour is faded 80% of the way from | |
255 | * blue(0, 0, 255) to white(255, 255, 255) | |
256 | * making (204, 204, 255) | |
257 | */ | |
258 | 1 | assertEquals(new Color(204, 204, 255), rs.findColour('Q', 7, null)); |
259 | ||
260 | /* | |
261 | * turn off By Conservation, apply Above Identity Threshold | |
262 | * providing a stub Consensus that has modal residue "Q" with pid 60% | |
263 | */ | |
264 | 1 | rs.setConservationApplied(false); |
265 | 1 | ProfilesI consensus = getStubConsensus("Q", 60f); |
266 | 1 | rs.setConsensus(consensus); |
267 | ||
268 | // with consensus pid (60) above threshold (50), colours are unchanged | |
269 | 1 | rs.setThreshold(50, false); |
270 | 1 | assertEquals(Color.blue, rs.findColour('Q', 7, null)); |
271 | 1 | assertEquals(Color.red, rs.findColour('-', 7, null)); |
272 | ||
273 | // with consensus pid (60) below threshold (70), | |
274 | // residue colour becomes white, gap colour is unchanged | |
275 | 1 | rs.setThreshold(70, false); |
276 | 1 | assertEquals(Color.white, rs.findColour('Q', 7, null)); |
277 | 1 | assertEquals(Color.red, rs.findColour('-', 7, null)); |
278 | } | |
279 | ||
280 | /** | |
281 | * @param modalResidue | |
282 | * @param pid | |
283 | * @return | |
284 | */ | |
285 | 1 | protected ProfilesI getStubConsensus(final String modalResidue, |
286 | final float pid) | |
287 | { | |
288 | 1 | ProfilesI consensus = new ProfilesI() |
289 | { | |
290 | ||
291 | 6 | @Override |
292 | public ProfileI get(int i) | |
293 | { | |
294 | 6 | return new ProfileI() |
295 | { | |
296 | 0 | @Override |
297 | public void setCounts(ResidueCount residueCounts) | |
298 | { | |
299 | } | |
300 | ||
301 | 6 | @Override |
302 | public float getPercentageIdentity(boolean ignoreGaps) | |
303 | { | |
304 | 6 | return pid; |
305 | } | |
306 | ||
307 | 0 | @Override |
308 | public ResidueCount getCounts() | |
309 | { | |
310 | 0 | return null; |
311 | } | |
312 | ||
313 | 0 | @Override |
314 | public int getHeight() | |
315 | { | |
316 | 0 | return 0; |
317 | } | |
318 | ||
319 | 0 | @Override |
320 | public int getGapped() | |
321 | { | |
322 | 0 | return 0; |
323 | } | |
324 | ||
325 | 0 | @Override |
326 | public int getMaxCount() | |
327 | { | |
328 | 0 | return 0; |
329 | } | |
330 | ||
331 | 6 | @Override |
332 | public String getModalResidue() | |
333 | { | |
334 | 6 | return modalResidue; |
335 | } | |
336 | ||
337 | 0 | @Override |
338 | public int getNonGapped() | |
339 | { | |
340 | 0 | return 0; |
341 | } | |
342 | ||
343 | 0 | @Override |
344 | public void setSSCounts( | |
345 | SecondaryStructureCount secondaryStructureCount) | |
346 | { | |
347 | // TODO Auto-generated method stub | |
348 | ||
349 | } | |
350 | ||
351 | 0 | @Override |
352 | public float getSSPercentageIdentity(boolean ignoreGaps) | |
353 | { | |
354 | // TODO Auto-generated method stub | |
355 | 0 | return 0; |
356 | } | |
357 | ||
358 | 0 | @Override |
359 | public int getMaxSSCount() | |
360 | { | |
361 | // TODO Auto-generated method stub | |
362 | 0 | return 0; |
363 | } | |
364 | ||
365 | 0 | @Override |
366 | public String getModalSS() | |
367 | { | |
368 | // TODO Auto-generated method stub | |
369 | 0 | return null; |
370 | } | |
371 | ||
372 | 0 | @Override |
373 | public SecondaryStructureCount getSSCounts() | |
374 | { | |
375 | // TODO Auto-generated method stub | |
376 | 0 | return null; |
377 | } | |
378 | ||
379 | 0 | @Override |
380 | public int getSeqWithSSCount() | |
381 | { | |
382 | // TODO Auto-generated method stub | |
383 | 0 | return 0; |
384 | } | |
385 | }; | |
386 | } | |
387 | ||
388 | 0 | @Override |
389 | public int getStartColumn() | |
390 | { | |
391 | 0 | return 0; |
392 | } | |
393 | ||
394 | 0 | @Override |
395 | public int getEndColumn() | |
396 | { | |
397 | 0 | return 0; |
398 | } | |
399 | ||
400 | }; | |
401 | 1 | return consensus; |
402 | } | |
403 | } |