Class |
Line # |
Actions |
|||
---|---|---|---|---|---|
Mapping | 42 | 109 | 18 |
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.structure; | |
22 | ||
23 | import static org.testng.AssertJUnit.assertEquals; | |
24 | import static org.testng.AssertJUnit.assertTrue; | |
25 | ||
26 | import org.testng.Assert; | |
27 | import org.testng.AssertJUnit; | |
28 | import org.testng.annotations.BeforeClass; | |
29 | import org.testng.annotations.Test; | |
30 | ||
31 | import jalview.datamodel.AlignmentAnnotation; | |
32 | import jalview.datamodel.Annotation; | |
33 | import jalview.datamodel.Sequence; | |
34 | import jalview.datamodel.SequenceI; | |
35 | import jalview.gui.AlignFrame; | |
36 | import jalview.gui.JvOptionPane; | |
37 | import jalview.io.DataSourceType; | |
38 | import jalview.io.FileFormat; | |
39 | import jalview.io.FileLoader; | |
40 | import jalview.io.StructureFile; | |
41 | ||
42 | public class Mapping | |
43 | { | |
44 | ||
45 | 1 | @BeforeClass(alwaysRun = true) |
46 | public void setUpJvOptionPane() | |
47 | { | |
48 | 1 | JvOptionPane.setInteractiveMode(false); |
49 | 1 | JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION); |
50 | } | |
51 | ||
52 | /* | |
53 | * more test data | |
54 | * | |
55 | * 1QCF|A/101-121 SFQKGDQMVVLEESGEWWKAR Ser 114 jumps to Gly 116 at position | |
56 | * 115 in PDB Res Numbering secondary structure numbers in jmol seem to be in | |
57 | * msd numbering, not pdb res numbering. | |
58 | */ | |
59 | 0 | @Test(groups = { "Functional" }, enabled = false) |
60 | public void pdbEntryPositionMap() throws Exception | |
61 | { | |
62 | 0 | Assert.fail("This test intentionally left to fail"); |
63 | 0 | for (int offset = 0; offset < 20; offset += 6) |
64 | { | |
65 | // check we put the secondary structure in the right position | |
66 | 0 | Sequence uprot = new Sequence("TheProtSeq", |
67 | "DAWEIPRESLKLEKKLGAGQFGEVWMATYNKHTKVAVKTMKPGSMSVEAFLAEANVMKTL"); | |
68 | 0 | uprot.setStart(offset + 258); // make it harder - create a fake |
69 | // relocation problem for jalview to | |
70 | // deal with | |
71 | 0 | uprot.setEnd(uprot.getStart() + uprot.getLength() - 1); |
72 | // original numbers taken from | |
73 | // http://www.ebi.ac.uk/pdbe-srv/view/entry/1qcf/secondary.html | |
74 | // these are in numbering relative to the subsequence above | |
75 | 0 | int coils[] = { 266, 275, 278, 287, 289, 298, 302, 316 }, |
76 | helices[] = new int[] | |
77 | { 303, 315 }, sheets[] = new int[] { 267, 268, 269, 270 }; | |
78 | ||
79 | 0 | StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager(); |
80 | 0 | StructureFile pmap = ssm.setMapping(true, new SequenceI[] { uprot }, |
81 | new String[] | |
82 | { "A" }, "test/jalview/ext/jmol/1QCF.pdb", | |
83 | DataSourceType.FILE, null, null); | |
84 | 0 | assertTrue(pmap != null); |
85 | 0 | SequenceI protseq = pmap.getSeqsAsArray()[0]; |
86 | 0 | AlignmentAnnotation pstra = protseq |
87 | .getAnnotation("Secondary Structure")[0]; | |
88 | 0 | int pinds, pinde; |
89 | 0 | pstra.restrict((pinds = protseq.findIndex(258) - 1), |
90 | pinde = (protseq.findIndex(317) - 1)); | |
91 | 0 | int op; |
92 | 0 | System.out.println("PDB Annot"); |
93 | 0 | for (char c : protseq.getSubSequence(pinds, pinde).getSequence()) |
94 | { | |
95 | 0 | System.out.print(c + ", "); |
96 | } | |
97 | 0 | System.out.println("\n" + pstra + "\n\nsubsequence\n"); |
98 | 0 | for (char c : uprot.getSequence()) |
99 | { | |
100 | 0 | System.out.print(c + ", "); |
101 | } | |
102 | 0 | System.out.println(""); |
103 | 0 | for (AlignmentAnnotation ss : uprot |
104 | .getAnnotation("Secondary Structure")) | |
105 | { | |
106 | 0 | ss.adjustForAlignment(); |
107 | 0 | System.out.println("Uniprot Annot\n" + ss); |
108 | 0 | assertTrue(ss.hasIcons); |
109 | 0 | char expected = 'H'; |
110 | 0 | for (int p : helices) |
111 | { | |
112 | 0 | Annotation a = ss.annotations[op = (uprot.findIndex(offset + p) |
113 | - 1)]; | |
114 | 0 | assertTrue("Expected a helix at position " + p |
115 | + uprot.getCharAt(op) + " but got coil", a != null); | |
116 | 0 | assertEquals("Expected a helix at position " + p, |
117 | a.secondaryStructure, expected); | |
118 | } | |
119 | 0 | expected = 'E'; |
120 | 0 | for (int p : sheets) |
121 | { | |
122 | 0 | Annotation a = ss.annotations[uprot.findIndex(offset + p) - 1]; |
123 | 0 | assertTrue("Expected a strand at position " + p + " but got coil", |
124 | a != null); | |
125 | 0 | assertEquals("Expected a strand at position " + p, |
126 | a.secondaryStructure, expected); | |
127 | } | |
128 | 0 | expected = ' '; |
129 | 0 | for (int p : coils) |
130 | { | |
131 | 0 | Annotation a = ss.annotations[uprot.findIndex(offset + p) - 1]; |
132 | 0 | assertTrue("Expected coil at position " + p + " but got " |
133 | + a.secondaryStructure, a == null); | |
134 | } | |
135 | } | |
136 | } | |
137 | } | |
138 | ||
139 | 0 | @Test(groups = { "Functional" }, enabled = false) |
140 | public void testPDBentryMapping() throws Exception | |
141 | { | |
142 | 0 | Assert.fail("This test intentionally left to fail"); |
143 | 0 | Sequence sq = new Sequence("1GAQ A subseq 126 to 219", |
144 | "EIVKGVCSNFLCDLQPGDNVQITGPVGKEMLMPKDPNATIIMLATGTGIAPFRSFLWKMFFEKHDDYKFNGLGWLFLGVPTSSSLLYKEEFGKM"); | |
145 | 0 | Sequence sq1 = new Sequence(sq); |
146 | 0 | String inFile; |
147 | 0 | StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager(); |
148 | // Associate the 1GAQ pdb file with the subsequence 'imported' from another | |
149 | // source | |
150 | 0 | StructureFile pde = ssm.setMapping(true, new SequenceI[] { sq }, |
151 | new String[] | |
152 | { "A" }, inFile = "examples/1gaq.txt", DataSourceType.FILE, | |
153 | null, null); | |
154 | 0 | assertTrue("PDB File couldn't be found", pde != null); |
155 | 0 | StructureMapping[] mp = ssm.getMapping(inFile); |
156 | 0 | assertTrue("No mappings made.", mp != null && mp.length > 0); |
157 | 0 | int nsecStr = 0, nsTemp = 0; |
158 | // test for presence of transferred annotation on sequence | |
159 | 0 | for (AlignmentAnnotation alan : sq.getAnnotation()) |
160 | { | |
161 | 0 | if (alan.hasIcons) |
162 | { | |
163 | 0 | nsecStr++; |
164 | } | |
165 | 0 | if (alan.graph == alan.LINE_GRAPH) |
166 | { | |
167 | 0 | nsTemp++; |
168 | } | |
169 | } | |
170 | 0 | assertEquals( |
171 | "Only one secondary structure should be transferred to associated sequence.", | |
172 | 1, nsecStr); | |
173 | 0 | assertEquals( |
174 | "Only two line graphs should be transferred to associated sequence.", | |
175 | 2, nsTemp); | |
176 | // Now test the transfer function and compare annotated positions | |
177 | 0 | for (StructureMapping origMap : mp) |
178 | { | |
179 | 0 | if (origMap.getSequence() == sq) |
180 | { | |
181 | 0 | assertEquals("Mapping was incomplete.", sq.getLength() - 1, |
182 | (origMap.getPDBResNum(sq.getEnd()) | |
183 | - origMap.getPDBResNum(sq.getStart()))); | |
184 | // sanity check - if this fails, mapping from first position in sequence | |
185 | // we want to transfer to is not where we expect | |
186 | 0 | assertEquals(1, origMap.getSeqPos(126)); |
187 | 0 | SequenceI firstChain = pde.getSeqs().get(0); |
188 | // Compare the annotated positions on the PDB chain sequence with the | |
189 | // annotation on the associated sequence | |
190 | 0 | for (AlignmentAnnotation alan : firstChain.getAnnotation()) |
191 | { | |
192 | 0 | AlignmentAnnotation transfer = origMap.transfer(alan); |
193 | 0 | System.out.println("pdb:" + firstChain.getSequenceAsString()); |
194 | 0 | System.out.println("ann:" + alan.toString()); |
195 | 0 | System.out.println("pdb:" + sq.getSequenceAsString()); |
196 | 0 | System.out.println("ann:" + transfer.toString()); |
197 | ||
198 | 0 | for (int p = 0, pSize = firstChain.getLength(); p < pSize; p++) |
199 | { | |
200 | // walk along the pdb chain's jalview sequence | |
201 | 0 | int rseqpos; |
202 | 0 | int fpos = origMap |
203 | .getSeqPos(rseqpos = firstChain.findPosition(p)); | |
204 | // only look at positions where there is a corresponding position in | |
205 | // mapping | |
206 | 0 | if (fpos < 1) |
207 | { | |
208 | 0 | continue; |
209 | } | |
210 | // p is index into PDB residue entries | |
211 | // rseqpos is pdb sequence position for position p | |
212 | // fpos is sequence position for associated position for rseqpos | |
213 | // tanpos is the column for the mapped sequence position | |
214 | 0 | int tanpos = sq.findIndex(fpos) - 1; |
215 | 0 | if (tanpos < 0 || transfer.annotations.length <= tanpos) |
216 | { | |
217 | // gone beyond mapping to the sequence | |
218 | 0 | break; |
219 | } | |
220 | ||
221 | 0 | Annotation a = transfer.annotations[tanpos], |
222 | b = alan.annotations[p]; | |
223 | 0 | assertEquals( |
224 | "Non-equivalent annotation element at " + p + "(" | |
225 | + rseqpos + ")" + " expected at " + fpos | |
226 | + " (alIndex " + tanpos + ")", | |
227 | 0 | a == null ? a : a.toString(), |
228 | 0 | b == null ? b : b.toString()); |
229 | 0 | System.out.print("(" + a + "|" + b + ")"); |
230 | } | |
231 | ||
232 | } | |
233 | } | |
234 | } | |
235 | } | |
236 | ||
237 | /** | |
238 | * corner case for pdb mapping - revealed a problem with the AlignSeq->Mapping | |
239 | * transform | |
240 | * | |
241 | */ | |
242 | 1 | @Test(groups = { "Functional" }) |
243 | public void mapFer1From3W5V() throws Exception | |
244 | { | |
245 | 1 | AlignFrame seqf = new FileLoader(false).LoadFileWaitTillLoaded( |
246 | ">FER1_MAIZE/1-150 Ferredoxin-1, chloroplast precursor\nMATVLGSPRAPAFFFSSSSLRAAPAPTAVALPAAKVGIMGRSASSRRRLRAQATYNVKLITPEGEVELQVPD\nDVYILDQAEEDGIDLPYSCRAGSCSSCAGKVVSGSVDQSDQSYLDDGQIADGWVLTCHAYPTSDVVIETHKE\nEELTGA", | |
247 | DataSourceType.PASTE, FileFormat.Fasta); | |
248 | 1 | SequenceI newseq = seqf.getViewport().getAlignment().getSequenceAt(0); |
249 | 1 | StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager(); |
250 | 1 | StructureFile pmap = ssm.setMapping(true, new SequenceI[] { newseq }, |
251 | new String[] | |
252 | { null }, "examples/3W5V.pdb", DataSourceType.FILE, null, null); | |
253 | 1 | if (pmap == null) |
254 | { | |
255 | 0 | AssertJUnit.fail("Couldn't make a mapping for 3W5V to FER1_MAIZE"); |
256 | } | |
257 | } | |
258 | ||
259 | /** | |
260 | * compare reference annotation for imported pdb sequence to identical | |
261 | * seuqence with transferred annotation from mapped pdb file | |
262 | */ | |
263 | 1 | @Test(groups = { "Functional" }) |
264 | public void compareTransferredToRefPDBAnnot() throws Exception | |
265 | { | |
266 | 1 | StructureImportSettings.setProcessSecondaryStructure(true); |
267 | 1 | StructureImportSettings.setVisibleChainAnnotation(true); |
268 | 1 | StructureImportSettings.setShowSeqFeatures(true); |
269 | 1 | AlignFrame ref = new FileLoader(false).LoadFileWaitTillLoaded( |
270 | "test/jalview/ext/jmol/1QCF.pdb", DataSourceType.FILE); | |
271 | 1 | SequenceI refseq = ref.getViewport().getAlignment().getSequenceAt(0); |
272 | 1 | SequenceI newseq = new Sequence(refseq.getName() + "Copy", |
273 | refseq.getSequenceAsString()); | |
274 | // make it harder by shifting the copy vs the reference | |
275 | 1 | newseq.setStart(refseq.getStart() + 25); |
276 | 1 | newseq.setEnd(refseq.getLength() + 25 + refseq.getStart()); |
277 | 1 | StructureSelectionManager ssm = new jalview.structure.StructureSelectionManager(); |
278 | 1 | ssm.setProcessSecondaryStructure(true); |
279 | 1 | ssm.setAddTempFacAnnot(true); |
280 | 1 | StructureFile pmap = ssm.setMapping(true, new SequenceI[] { newseq }, |
281 | new String[] | |
282 | { null }, "test/jalview/ext/jmol/1QCF.pdb", DataSourceType.FILE, | |
283 | null, null); | |
284 | 1 | assertTrue(pmap != null); |
285 | 1 | assertEquals("Original and copied sequence of different lengths.", |
286 | refseq.getLength(), newseq.getLength()); | |
287 | 1 | assertTrue(refseq.getAnnotation() != null |
288 | && refseq.getAnnotation().length > 0); | |
289 | 1 | assertTrue(newseq.getAnnotation() != null |
290 | && newseq.getAnnotation().length > 0); | |
291 | 1 | for (AlignmentAnnotation oannot : refseq.getAnnotation()) |
292 | { | |
293 | 2 | for (AlignmentAnnotation tannot : newseq.getAnnotation(oannot.label)) |
294 | { | |
295 | 902 | for (int p = 0, pSize = refseq.getLength(); p < pSize; p++) |
296 | { | |
297 | 900 | Annotation orig = oannot.annotations[p], |
298 | tran = tannot.annotations[p]; | |
299 | 900 | assertTrue("Mismatch: coil and non coil site " + p, |
300 | orig == tran || orig != null && tran != null); | |
301 | 900 | if (tran != null) |
302 | { | |
303 | 678 | assertEquals("Mismatch in secondary structure at site " + p, |
304 | tran.secondaryStructure, orig.secondaryStructure); | |
305 | } | |
306 | } | |
307 | } | |
308 | } | |
309 | } | |
310 | } |