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