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