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