JAL-2629 fix expected length error for hmmbuild by uniquifying sequences
[jalview.git] / test / MCview / PDBfileTest.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 MCview;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertFalse;
25 import static org.testng.AssertJUnit.assertNull;
26 import static org.testng.AssertJUnit.assertSame;
27 import static org.testng.AssertJUnit.assertTrue;
28
29 import jalview.bin.Cache;
30 import jalview.datamodel.Alignment;
31 import jalview.datamodel.AlignmentAnnotation;
32 import jalview.datamodel.AlignmentI;
33 import jalview.datamodel.PDBEntry;
34 import jalview.datamodel.Sequence;
35 import jalview.datamodel.SequenceI;
36 import jalview.gui.JvOptionPane;
37 import jalview.io.DataSourceType;
38 import jalview.structure.StructureImportSettings;
39
40 import java.io.IOException;
41 import java.util.List;
42
43 import org.testng.annotations.BeforeClass;
44 import org.testng.annotations.BeforeMethod;
45 import org.testng.annotations.Test;
46
47 public class PDBfileTest
48 {
49
50   @BeforeClass(alwaysRun = true)
51   public void setUpJvOptionPane()
52   {
53     JvOptionPane.setInteractiveMode(false);
54     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
55   }
56
57   @Test(groups = { "Functional" })
58   public void testIsRna()
59   {
60     SequenceI seq = new Sequence("Seq1", "CGAU");
61     assertTrue(PDBfile.isRNA(seq));
62
63     seq.setSequence("CGAu");
64     assertFalse(PDBfile.isRNA(seq));
65
66     seq.setSequence("CGAT");
67     assertFalse(PDBfile.isRNA(seq));
68
69     seq.setSequence("GRSWYFLAVM");
70     assertFalse(PDBfile.isRNA(seq));
71   }
72
73   /**
74    * Test the 'high level' outputs of parsing. More detailed tests in
75    * PDBChainTest.
76    * 
77    * @throws IOException
78    */
79   @Test(groups = { "Functional" })
80   public void testParse() throws IOException
81   {
82     /*
83      * Constructor with file path performs parse()
84      */
85     PDBfile pf = new PDBfile(false, false, false, "examples/3W5V.pdb",
86             DataSourceType.FILE);
87
88     assertEquals("3W5V", pf.getId());
89     // verify no alignment annotations created
90     assertNull(getAlignmentAnnotations(pf));
91
92     assertEquals(4, pf.getChains().size());
93     assertEquals("A", pf.getChains().get(0).id);
94     assertEquals("B", pf.getChains().get(1).id);
95     assertEquals("C", pf.getChains().get(2).id);
96     assertEquals("D", pf.getChains().get(3).id);
97
98     PDBChain chainA = pf.getChains().get(0);
99     SequenceI seqA = pf.getSeqs().get(0);
100
101     assertEquals(0, chainA.seqstart); // not set
102     assertEquals(0, chainA.seqend); // not set
103     assertEquals(18, chainA.sequence.getStart());
104     assertEquals(314, chainA.sequence.getEnd());
105     assertTrue(chainA.sequence.getSequenceAsString().startsWith("KCSKKQEE"));
106     assertTrue(chainA.sequence.getSequenceAsString().endsWith("WNVEVY"));
107     assertEquals("3W5V|A", chainA.sequence.getName());
108     assertNull(chainA.sequence.getAnnotation());
109     assertEquals(1, seqA.getAllPDBEntries().size());
110     PDBEntry pdb = seqA.getAllPDBEntries().get(0);
111     assertEquals("A", pdb.getChainCode());
112     assertEquals("PDB", pdb.getType());
113     assertEquals("3W5V", pdb.getId());
114
115     PDBChain chainB = pf.getChains().get(1);
116     assertEquals(1, chainB.sequence.getStart());
117     assertEquals(96, chainB.sequence.getEnd());
118     assertTrue(chainB.sequence.getSequenceAsString().startsWith("ATYNVK"));
119     assertTrue(chainB.sequence.getSequenceAsString().endsWith("KEEELT"));
120     assertEquals("3W5V|B", chainB.sequence.getName());
121
122     PDBChain chainC = pf.getChains().get(2);
123     assertEquals(18, chainC.sequence.getStart());
124     assertEquals(314, chainC.sequence.getEnd());
125     assertTrue(chainC.sequence.getSequenceAsString().startsWith("KCSKKQEE"));
126     assertTrue(chainC.sequence.getSequenceAsString().endsWith("WNVEVY"));
127     assertEquals("3W5V|C", chainC.sequence.getName());
128
129     PDBChain chainD = pf.getChains().get(3);
130     assertEquals(1, chainD.sequence.getStart());
131     assertEquals(96, chainD.sequence.getEnd());
132     assertTrue(chainD.sequence.getSequenceAsString().startsWith("ATYNVK"));
133     assertTrue(chainD.sequence.getSequenceAsString().endsWith("KEEELT"));
134     assertEquals("3W5V|D", chainD.sequence.getName());
135
136     /*
137      * verify PDB-related data in parsed sequences
138      */
139     List<SequenceI> seqs = pf.getSeqs();
140     assertEquals(4, seqs.size());
141     assertEquals("3W5V|A", seqs.get(0).getName());
142     assertEquals("3W5V|B", seqs.get(1).getName());
143     assertEquals("3W5V|C", seqs.get(2).getName());
144     assertEquals("3W5V|D", seqs.get(3).getName());
145     assertEquals(1, seqs.get(0).getAllPDBEntries().size());
146     PDBEntry pdbe = seqs.get(0).getAllPDBEntries().get(0);
147     assertEquals("A", pdbe.getChainCode());
148     assertEquals("3W5V", pdbe.getId());
149     assertEquals(PDBEntry.Type.PDB.toString(), pdbe.getType());
150   }
151
152   /**
153    * Test parsing, with annotations added to the alignment but no secondary
154    * structure prediction
155    * 
156    * @throws IOException
157    */
158   @Test(groups = { "Functional" })
159   public void testParse_withAnnotations_noSS() throws IOException
160   {
161     PDBfile pf = new PDBfile(true, false, false, "examples/3W5V.pdb",
162             DataSourceType.FILE);
163
164     AlignmentAnnotation[] anns = getAlignmentAnnotations(pf);
165     assertEquals(4, anns.length);
166
167     /*
168      * Inspect temp factor annotation for chain A
169      */
170     AlignmentAnnotation chainAnnotation = anns[0];
171     assertEquals("Temperature Factor", chainAnnotation.label);
172     // PDBChain constructor changes PDB id to lower case (why?)
173     assertEquals("Temperature Factor for 3w5vA",
174             chainAnnotation.description);
175     assertSame(pf.getSeqs().get(0), chainAnnotation.sequenceRef);
176     assertEquals(AlignmentAnnotation.LINE_GRAPH, chainAnnotation.graph);
177     assertEquals(0f, chainAnnotation.graphMin, 0.001f);
178     assertEquals(40f, chainAnnotation.graphMax, 0.001f);
179     assertEquals(297, chainAnnotation.annotations.length);
180     assertEquals(40f, chainAnnotation.annotations[0].value, 0.001f);
181
182     /*
183      * Chain B temp factor
184      */
185     chainAnnotation = anns[1];
186     assertEquals("Temperature Factor for 3w5vB",
187             chainAnnotation.description);
188     assertSame(pf.getSeqs().get(1), chainAnnotation.sequenceRef);
189     assertEquals(96, chainAnnotation.annotations.length);
190
191     /*
192      * Chain C temp factor
193      */
194     chainAnnotation = anns[2];
195     assertEquals("Temperature Factor for 3w5vC",
196             chainAnnotation.description);
197     assertSame(pf.getSeqs().get(2), chainAnnotation.sequenceRef);
198     assertEquals(297, chainAnnotation.annotations.length);
199
200     /*
201      * Chain D temp factor
202      */
203     chainAnnotation = anns[3];
204     assertEquals("Temperature Factor for 3w5vD",
205             chainAnnotation.description);
206     assertSame(pf.getSeqs().get(3), chainAnnotation.sequenceRef);
207     assertEquals(96, chainAnnotation.annotations.length);
208   }
209
210   /**
211    * Test parsing including secondary structure annotation using JMol; this test
212    * for the case where flag to add annotations to alignment is set false
213    * 
214    * @throws IOException
215    */
216   @Test(groups = { "Functional" })
217   public void testParse_withJmol_noAnnotations() throws IOException
218   {
219     PDBfile pf = new PDBfile(false, true, false, "examples/3W5V.pdb",
220             DataSourceType.FILE);
221
222     /*
223      * alignment annotations _are_ created anyway (in
224      * AlignSeq.replaceMatchingSeqsWith())
225      */
226     final AlignmentAnnotation[] anns = getAlignmentAnnotations(pf);
227     assertEquals(4, anns.length);
228
229     /*
230      * no sequence annotations created - tempFactor annotation is not added
231      * unless the flag to 'addAlignmentAnnotations' is set true
232      */
233     for (PDBChain c : pf.getChains())
234     {
235       assertNull(c.sequence.getAnnotation());
236     }
237   }
238
239   /**
240    * Test parsing including secondary structure prediction and annotation using
241    * JMol
242    * 
243    * @throws IOException
244    */
245   @Test(groups = { "Functional" })
246   public void testParse_withJmolAddAlignmentAnnotations()
247           throws IOException
248   {
249     PDBfile pf = new PDBfile(true, true, false, "examples/3W5V.pdb",
250             DataSourceType.FILE);
251
252     /*
253      * Alignment annotations for TempFactor, SecStruct, per sequence (chain)
254      */
255     AlignmentAnnotation[] anns = getAlignmentAnnotations(pf);
256     assertEquals(8, anns.length);
257
258     /*
259      * other tests have detailed assertions for Temp Factor annotations
260      */
261     assertEquals("Temperature Factor for 3w5vA", anns[1].description);
262     assertEquals("Temperature Factor for 3w5vB", anns[3].description);
263     assertEquals("Temperature Factor for 3w5vC", anns[5].description);
264     assertEquals("Temperature Factor for 3w5vD", anns[7].description);
265
266     /*
267      * PDBFileWithJmol (unlike PDBChain!) leaves PDB id upper case
268      */
269     assertEquals("Secondary Structure for 3w5vA", anns[0].description);
270     assertEquals("Secondary Structure for 3w5vB", anns[2].description);
271     assertEquals("Secondary Structure for 3w5vC", anns[4].description);
272     assertEquals("Secondary Structure for 3w5vD", anns[6].description);
273
274     /*
275      * Verify SS annotations are linked to respective sequences (chains)
276      */
277     assertSame(pf.getSeqs().get(0), anns[0].sequenceRef);
278     assertSame(pf.getSeqs().get(1), anns[2].sequenceRef);
279     assertSame(pf.getSeqs().get(2), anns[4].sequenceRef);
280     assertSame(pf.getSeqs().get(3), anns[6].sequenceRef);
281
282     /*
283      * Verify a sample of SS predictions
284      */
285     for (int i = 0; i < 20; i++)
286     {
287       assertNull(anns[0].annotations[i]);
288       assertEquals("E", anns[0].annotations[20].displayCharacter);
289       assertEquals('E', anns[0].annotations[20].secondaryStructure);
290       assertEquals("E", anns[2].annotations[18].displayCharacter);
291       assertEquals("H", anns[2].annotations[23].displayCharacter);
292     }
293   }
294
295   /**
296    * Placeholder for a test of parsing RNA structure with secondary structure
297    * prediction using the Annotate3D service
298    * 
299    * @throws IOException
300    */
301
302   @Test(groups = { "Functional" }, enabled = false)
303   public void testParse_withAnnotate3D() throws IOException
304   {
305     // TODO requires a mock for Annotate3D processing
306     // and/or run as an integration test
307     PDBfile pf = new PDBfile(true, true, true, "examples/2GIS.pdb",
308             DataSourceType.FILE);
309   }
310
311   /**
312    * Helper method to extract parsed annotations from the PDBfile
313    * 
314    * @param pf
315    * @return
316    */
317   private AlignmentAnnotation[] getAlignmentAnnotations(PDBfile pf)
318   {
319     AlignmentI al = new Alignment(pf.getSeqsAsArray());
320     pf.addAnnotations(al);
321     return al.getAlignmentAnnotation();
322   }
323
324   @BeforeMethod(alwaysRun = true)
325   public void setUp()
326   {
327     Cache.loadProperties("test/jalview/io/testProps.jvprops");
328     Cache.applicationProperties.setProperty("STRUCT_FROM_PDB",
329             Boolean.TRUE.toString());
330     Cache.applicationProperties.setProperty("ADD_TEMPFACT_ANN",
331             Boolean.TRUE.toString());
332     Cache.applicationProperties.setProperty("ADD_SS_ANN",
333             Boolean.TRUE.toString());
334     StructureImportSettings.setDefaultStructureFileFormat("PDB");
335   }
336 }