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