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