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