Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
SequenceFeatureTest | 38 | 167 | 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.datamodel; | |
22 | ||
23 | import static org.testng.AssertJUnit.assertEquals; | |
24 | import static org.testng.AssertJUnit.assertFalse; | |
25 | import static org.testng.AssertJUnit.assertNull; | |
26 | import static org.testng.AssertJUnit.assertSame; | |
27 | import static org.testng.AssertJUnit.assertTrue; | |
28 | ||
29 | import java.util.ArrayList; | |
30 | import java.util.List; | |
31 | ||
32 | import org.testng.annotations.BeforeClass; | |
33 | import org.testng.annotations.Test; | |
34 | ||
35 | import jalview.gui.JvOptionPane; | |
36 | import jalview.util.MapList; | |
37 | ||
38 | public class SequenceFeatureTest | |
39 | { | |
40 | ||
41 | 1 | @BeforeClass(alwaysRun = true) |
42 | public void setUpJvOptionPane() | |
43 | { | |
44 | 1 | JvOptionPane.setInteractiveMode(false); |
45 | 1 | JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); |
46 | } | |
47 | ||
48 | 1 | @Test(groups = { "Functional" }) |
49 | public void testCopyConstructors() | |
50 | { | |
51 | 1 | SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
52 | "group"); | |
53 | 1 | sf1.setValue("STRAND", "+"); |
54 | 1 | sf1.setValue("Note", "Testing"); |
55 | 1 | Integer count = Integer.valueOf(7); |
56 | 1 | sf1.setValue("Count", count); |
57 | ||
58 | 1 | SequenceFeature sf2 = new SequenceFeature(sf1); |
59 | 1 | assertEquals("type", sf2.getType()); |
60 | 1 | assertEquals("desc", sf2.getDescription()); |
61 | 1 | assertEquals(22, sf2.getBegin()); |
62 | 1 | assertEquals(33, sf2.getEnd()); |
63 | 1 | assertEquals(12.5f, sf2.getScore()); |
64 | 1 | assertEquals("+", sf2.getValue("STRAND")); |
65 | 1 | assertEquals("Testing", sf2.getValue("Note")); |
66 | // shallow clone of otherDetails map - contains the same object values! | |
67 | 1 | assertSame(count, sf2.getValue("Count")); |
68 | ||
69 | /* | |
70 | * copy constructor modifying begin/end/group/score | |
71 | */ | |
72 | 1 | SequenceFeature sf3 = new SequenceFeature(sf1, 11, 14, "group2", 17.4f); |
73 | 1 | assertEquals("type", sf3.getType()); |
74 | 1 | assertEquals("desc", sf3.getDescription()); |
75 | 1 | assertEquals(11, sf3.getBegin()); |
76 | 1 | assertEquals(14, sf3.getEnd()); |
77 | 1 | assertEquals(17.4f, sf3.getScore()); |
78 | 1 | assertEquals("+", sf3.getValue("STRAND")); |
79 | 1 | assertEquals("Testing", sf3.getValue("Note")); |
80 | // shallow clone of otherDetails map - contains the same object values! | |
81 | 1 | assertSame(count, sf3.getValue("Count")); |
82 | ||
83 | /* | |
84 | * copy constructor modifying type/begin/end/group/score | |
85 | */ | |
86 | 1 | SequenceFeature sf4 = new SequenceFeature(sf1, "Disulfide bond", 12, 15, |
87 | "group3", -9.1f); | |
88 | 1 | assertEquals("Disulfide bond", sf4.getType()); |
89 | 1 | assertTrue(sf4.isContactFeature()); |
90 | 1 | assertEquals("desc", sf4.getDescription()); |
91 | 1 | assertEquals(12, sf4.getBegin()); |
92 | 1 | assertEquals(15, sf4.getEnd()); |
93 | 1 | assertEquals(-9.1f, sf4.getScore()); |
94 | 1 | assertEquals("+", sf4.getValue("STRAND")); |
95 | 1 | assertEquals("Testing", sf4.getValue("Note")); |
96 | // shallow clone of otherDetails map - contains the same object values! | |
97 | 1 | assertSame(count, sf4.getValue("Count")); |
98 | } | |
99 | ||
100 | /** | |
101 | * Tests for retrieving a 'miscellaneous details' property value, with or | |
102 | * without a supplied default | |
103 | */ | |
104 | 1 | @Test(groups = { "Functional" }) |
105 | public void testGetValue() | |
106 | { | |
107 | 1 | SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
108 | "group"); | |
109 | 1 | sf1.setValue("STRAND", "+"); |
110 | 1 | assertEquals("+", sf1.getValue("STRAND")); |
111 | 1 | assertNull(sf1.getValue("strand")); // case-sensitive |
112 | 1 | assertEquals(".", sf1.getValue("unknown", ".")); |
113 | 1 | Integer i = Integer.valueOf(27); |
114 | 1 | assertSame(i, sf1.getValue("Unknown", i)); |
115 | } | |
116 | ||
117 | /** | |
118 | * Tests the method that returns 1 / -1 / 0 for strand "+" / "-" / other | |
119 | */ | |
120 | 1 | @Test(groups = { "Functional" }) |
121 | public void testGetStrand() | |
122 | { | |
123 | 1 | SequenceFeature sf = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
124 | "group"); | |
125 | 1 | assertEquals(0, sf.getStrand()); |
126 | 1 | sf.setValue("STRAND", "+"); |
127 | 1 | assertEquals(1, sf.getStrand()); |
128 | 1 | sf.setValue("STRAND", "-"); |
129 | 1 | assertEquals(-1, sf.getStrand()); |
130 | 1 | sf.setValue("STRAND", "."); |
131 | 1 | assertEquals(0, sf.getStrand()); |
132 | } | |
133 | ||
134 | /** | |
135 | * Tests for equality, and that equal objects have the same hashCode | |
136 | */ | |
137 | 1 | @Test(groups = { "Functional" }) |
138 | public void testEqualsAndHashCode() | |
139 | { | |
140 | 1 | SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
141 | "group"); | |
142 | 1 | sf1.setValue("ID", "id"); |
143 | 1 | sf1.setValue("Name", "name"); |
144 | 1 | sf1.setValue("Parent", "parent"); |
145 | 1 | sf1.setStrand("+"); |
146 | 1 | sf1.setPhase("1"); |
147 | 1 | SequenceFeature sf2 = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
148 | "group"); | |
149 | 1 | sf2.setValue("ID", "id"); |
150 | 1 | sf2.setValue("Name", "name"); |
151 | 1 | sf2.setValue("Parent", "parent"); |
152 | 1 | sf2.setStrand("+"); |
153 | 1 | sf2.setPhase("1"); |
154 | ||
155 | 1 | assertFalse(sf1.equals(null)); |
156 | 1 | assertTrue(sf1.equals(sf2)); |
157 | 1 | assertTrue(sf2.equals(sf1)); |
158 | 1 | assertEquals(sf1.hashCode(), sf2.hashCode()); |
159 | ||
160 | // changing type breaks equals: | |
161 | 1 | SequenceFeature sf3 = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
162 | "group"); | |
163 | 1 | SequenceFeature sf4 = new SequenceFeature("Type", "desc", 22, 33, 12.5f, |
164 | "group"); | |
165 | 1 | assertFalse(sf3.equals(sf4)); |
166 | ||
167 | // changing description breaks equals: | |
168 | 1 | String restores = sf2.getDescription(); |
169 | 1 | sf2.setDescription("Desc"); |
170 | 1 | assertFalse(sf1.equals(sf2)); |
171 | 1 | sf2.setDescription(restores); |
172 | ||
173 | // changing score breaks equals: | |
174 | 1 | float restoref = sf2.getScore(); |
175 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), |
176 | sf2.getFeatureGroup(), 10f); | |
177 | 1 | assertFalse(sf1.equals(sf2)); |
178 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), |
179 | sf2.getFeatureGroup(), restoref); | |
180 | ||
181 | // NaN doesn't match a number | |
182 | 1 | restoref = sf2.getScore(); |
183 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), |
184 | sf2.getFeatureGroup(), Float.NaN); | |
185 | 1 | assertFalse(sf1.equals(sf2)); |
186 | ||
187 | // NaN matches NaN | |
188 | 1 | sf1 = new SequenceFeature(sf1, sf1.getBegin(), sf1.getEnd(), |
189 | sf1.getFeatureGroup(), Float.NaN); | |
190 | 1 | assertTrue(sf1.equals(sf2)); |
191 | 1 | sf1 = new SequenceFeature(sf1, sf1.getBegin(), sf1.getEnd(), |
192 | sf1.getFeatureGroup(), restoref); | |
193 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), |
194 | sf2.getFeatureGroup(), restoref); | |
195 | ||
196 | // changing start position breaks equals: | |
197 | 1 | int restorei = sf2.getBegin(); |
198 | 1 | sf2 = new SequenceFeature(sf2, 21, sf2.getEnd(), sf2.getFeatureGroup(), |
199 | sf2.getScore()); | |
200 | 1 | assertFalse(sf1.equals(sf2)); |
201 | 1 | sf2 = new SequenceFeature(sf2, restorei, sf2.getEnd(), |
202 | sf2.getFeatureGroup(), sf2.getScore()); | |
203 | ||
204 | // changing end position breaks equals: | |
205 | 1 | restorei = sf2.getEnd(); |
206 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), 32, |
207 | sf2.getFeatureGroup(), sf2.getScore()); | |
208 | 1 | assertFalse(sf1.equals(sf2)); |
209 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), restorei, |
210 | sf2.getFeatureGroup(), sf2.getScore()); | |
211 | ||
212 | // changing feature group breaks equals: | |
213 | 1 | restores = sf2.getFeatureGroup(); |
214 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), "Group", |
215 | sf2.getScore()); | |
216 | 1 | assertFalse(sf1.equals(sf2)); |
217 | 1 | sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), restores, |
218 | sf2.getScore()); | |
219 | ||
220 | // changing ID breaks equals: | |
221 | 1 | restores = (String) sf2.getValue("ID"); |
222 | 1 | sf2.setValue("ID", "id2"); |
223 | 1 | assertFalse(sf1.equals(sf2)); |
224 | 1 | sf2.setValue("ID", restores); |
225 | ||
226 | // changing Name breaks equals: | |
227 | 1 | restores = (String) sf2.getValue("Name"); |
228 | 1 | sf2.setValue("Name", "Name"); |
229 | 1 | assertFalse(sf1.equals(sf2)); |
230 | 1 | sf2.setValue("Name", restores); |
231 | ||
232 | // changing Parent breaks equals: | |
233 | 1 | restores = (String) sf1.getValue("Parent"); |
234 | 1 | sf1.setValue("Parent", "Parent"); |
235 | 1 | assertFalse(sf1.equals(sf2)); |
236 | 1 | sf1.setValue("Parent", restores); |
237 | ||
238 | // changing strand breaks equals: | |
239 | 1 | restorei = sf2.getStrand(); |
240 | 1 | sf2.setStrand("-"); |
241 | 1 | assertFalse(sf1.equals(sf2)); |
242 | 1 | sf2.setStrand(restorei == 1 ? "+" : "-"); |
243 | ||
244 | // changing phase breaks equals: | |
245 | 1 | restores = sf1.getPhase(); |
246 | 1 | sf1.setPhase("2"); |
247 | 1 | assertFalse(sf1.equals(sf2)); |
248 | 1 | sf1.setPhase(restores); |
249 | ||
250 | // restore equality as sanity check: | |
251 | 1 | assertTrue(sf1.equals(sf2)); |
252 | 1 | assertTrue(sf2.equals(sf1)); |
253 | 1 | assertEquals(sf1.hashCode(), sf2.hashCode()); |
254 | ||
255 | // changing status doesn't change equals: | |
256 | 1 | sf1.setStatus("new"); |
257 | 1 | assertTrue(sf1.equals(sf2)); |
258 | } | |
259 | ||
260 | 1 | @Test(groups = { "Functional" }) |
261 | public void testIsContactFeature() | |
262 | { | |
263 | 1 | SequenceFeature sf = new SequenceFeature("type", "desc", 22, 33, 12.5f, |
264 | "group"); | |
265 | 1 | assertFalse(sf.isContactFeature()); |
266 | 1 | sf = new SequenceFeature("", "desc", 22, 33, 12.5f, "group"); |
267 | 1 | assertFalse(sf.isContactFeature()); |
268 | 1 | sf = new SequenceFeature(null, "desc", 22, 33, 12.5f, "group"); |
269 | 1 | assertFalse(sf.isContactFeature()); |
270 | 1 | sf = new SequenceFeature("Disulfide Bond", "desc", 22, 33, 12.5f, |
271 | "group"); | |
272 | 1 | assertTrue(sf.isContactFeature()); |
273 | 1 | sf = new SequenceFeature("disulfide bond", "desc", 22, 33, 12.5f, |
274 | "group"); | |
275 | 1 | assertTrue(sf.isContactFeature()); |
276 | 1 | sf = new SequenceFeature("Disulphide Bond", "desc", 22, 33, 12.5f, |
277 | "group"); | |
278 | 1 | assertTrue(sf.isContactFeature()); |
279 | 1 | sf = new SequenceFeature("disulphide bond", "desc", 22, 33, 12.5f, |
280 | "group"); | |
281 | 1 | assertTrue(sf.isContactFeature()); |
282 | } | |
283 | ||
284 | 1 | @Test(groups = { "Functional" }) |
285 | public void testGetDetailsReport() | |
286 | { | |
287 | 1 | SequenceI seq = new Sequence("TestSeq", "PLRFQMD"); |
288 | 1 | String seqName = seq.getName(); |
289 | ||
290 | // single locus, no group, no score | |
291 | 1 | SequenceFeature sf = new SequenceFeature("variant", "G,C", 22, 22, |
292 | null); | |
293 | 1 | String expected = "<br><table><tr><td>Location</td><td>TestSeq</td><td>22</td></tr>" |
294 | + "<tr><td>Type</td><td>variant</td><td></td></tr>" | |
295 | + "<tr><td>Description</td><td>G,C</td><td></td></tr></table>"; | |
296 | 1 | assertEquals(expected, sf.getDetailsReport(seqName, null)); |
297 | ||
298 | // contact feature | |
299 | 1 | sf = new SequenceFeature("Disulphide Bond", "a description", 28, 31, |
300 | null); | |
301 | 1 | expected = "<br><table><tr><td>Location</td><td>TestSeq</td><td>28:31</td></tr>" |
302 | + "<tr><td>Type</td><td>Disulphide Bond</td><td></td></tr>" | |
303 | + "<tr><td>Description</td><td>a description</td><td></td></tr></table>"; | |
304 | 1 | assertEquals(expected, sf.getDetailsReport(seqName, null)); |
305 | ||
306 | 1 | sf = new SequenceFeature("variant", "G,C", 22, 33, 12.5f, "group"); |
307 | 1 | sf.setValue("Parent", "ENSG001"); |
308 | 1 | sf.setValue("Child", "ENSP002"); |
309 | 1 | expected = "<br><table><tr><td>Location</td><td>TestSeq</td><td>22-33</td></tr>" |
310 | + "<tr><td>Type</td><td>variant</td><td></td></tr>" | |
311 | + "<tr><td>Description</td><td>G,C</td><td></td></tr>" | |
312 | + "<tr><td>Score</td><td>12.5</td><td></td></tr>" | |
313 | + "<tr><td>Group</td><td>group</td><td></td></tr>" | |
314 | + "<tr><td>Child</td><td></td><td>ENSP002</td></tr>" | |
315 | + "<tr><td>Parent</td><td></td><td>ENSG001</td></tr></table>"; | |
316 | 1 | assertEquals(expected, sf.getDetailsReport(seqName, null)); |
317 | ||
318 | /* | |
319 | * feature with embedded html link in description | |
320 | */ | |
321 | 1 | String desc = "<html>Fer2 Status: True Positive <a href=\"http://pfam.xfam.org/family/PF00111\">Pfam 8_8</a></html>"; |
322 | 1 | sf = new SequenceFeature("Pfam", desc, 8, 83, "Uniprot"); |
323 | 1 | expected = "<br><table><tr><td>Location</td><td>TestSeq</td><td>8-83</td></tr>" |
324 | + "<tr><td>Type</td><td>Pfam</td><td></td></tr>" | |
325 | + "<tr><td>Description</td><td>Fer2 Status: True Positive <a href=\"http://pfam.xfam.org/family/PF00111\">Pfam 8_8</a></td><td></td></tr>" | |
326 | + "<tr><td>Group</td><td>Uniprot</td><td></td></tr></table>"; | |
327 | 1 | assertEquals(expected, sf.getDetailsReport(seqName, null)); |
328 | } | |
329 | ||
330 | /** | |
331 | * Feature details report for a virtual feature should include original and | |
332 | * mapped locations, and also derived peptide consequence if it can be | |
333 | * determined | |
334 | */ | |
335 | 1 | @Test(groups = { "Functional" }) |
336 | public void testGetDetailsReport_virtualFeature() | |
337 | { | |
338 | 1 | SequenceI cds = new Sequence("Cds/101-121", "CCTttgAGAtttCAAatgGAT"); |
339 | 1 | SequenceI seq = new Sequence("TestSeq/8-14", "PLRFQMD"); |
340 | 1 | MapList map = new MapList(new int[] { 101, 118 }, new int[] { 8, 13 }, |
341 | 3, 1); | |
342 | 1 | Mapping mapping = new Mapping(seq, map); |
343 | 1 | List<SequenceFeature> features = new ArrayList<>(); |
344 | // vary ttg (Leu) to ttc (Phe) | |
345 | 1 | SequenceFeature sf = new SequenceFeature("variant", "G,C", 106, 106, |
346 | null); | |
347 | 1 | sf.setValue("alleles", "G,C"); // needed to compute peptide consequence! |
348 | 1 | features.add(sf); |
349 | ||
350 | 1 | MappedFeatures mf = new MappedFeatures(mapping, cds, 9, 'L', features); |
351 | ||
352 | 1 | String expected = "<br><table><tr><td>Location</td><td>Cds</td><td>106</td></tr>" |
353 | + "<tr><td>Peptide Location</td><td>TestSeq</td><td>9</td></tr>" | |
354 | + "<tr><td>Type</td><td>variant</td><td></td></tr>" | |
355 | + "<tr><td>Description</td><td>G,C</td><td></td></tr>" | |
356 | + "<tr><td>Consequence</td><td><i>Translated by Jalview</i></td><td>p.Leu9Phe</td></tr>" | |
357 | + "<tr><td>alleles</td><td></td><td>G,C</td></tr>" + "</table>"; | |
358 | ||
359 | 1 | assertEquals(expected, sf.getDetailsReport(seq.getName(), mf)); |
360 | ||
361 | /* | |
362 | * exon feature extending beyond mapped range; mapped location should be | |
363 | * restricted to peptide mapped range limit i.e. 10-13 | |
364 | */ | |
365 | 1 | SequenceFeature sf2 = new SequenceFeature("exon", "exon 1", 109, 230, |
366 | null); | |
367 | 1 | features.add(sf2); |
368 | 1 | expected = "<br><table><tr><td>Location</td><td>Cds</td><td>109-230</td></tr>" |
369 | + "<tr><td>Peptide Location</td><td>TestSeq</td><td>10-13</td></tr>" | |
370 | + "<tr><td>Type</td><td>exon</td><td></td></tr>" | |
371 | + "<tr><td>Description</td><td>exon 1</td><td></td></tr>" | |
372 | + "</table>"; | |
373 | 1 | assertEquals(expected, sf2.getDetailsReport(seq.getName(), mf)); |
374 | } | |
375 | } |