Merge branch 'develop' (JAL-4102 2.11.2.6 patch release) into features/r2_11_2_alphaf...
[jalview.git] / test / jalview / ws / dbsources / UniprotTest.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.ws.dbsources;
22
23 import static org.testng.Assert.assertFalse;
24 import static org.testng.AssertJUnit.assertEquals;
25 import static org.testng.AssertJUnit.assertNotNull;
26 import static org.testng.AssertJUnit.assertNull;
27 import static org.testng.AssertJUnit.assertTrue;
28
29 import java.io.ByteArrayInputStream;
30 import java.io.InputStream;
31 import java.io.UnsupportedEncodingException;
32 import java.math.BigInteger;
33 import java.util.List;
34
35 import org.testng.Assert;
36 import org.testng.annotations.BeforeClass;
37 import org.testng.annotations.Test;
38
39 import jalview.datamodel.DBRefEntry;
40 import jalview.datamodel.DBRefSource;
41 import jalview.datamodel.SequenceI;
42 import jalview.gui.JvOptionPane;
43 import jalview.util.DBRefUtils;
44 import jalview.xml.binding.uniprot.DbReferenceType;
45 import jalview.xml.binding.uniprot.Entry;
46 import jalview.xml.binding.uniprot.FeatureType;
47 import jalview.xml.binding.uniprot.LocationType;
48 import jalview.xml.binding.uniprot.PositionType;
49
50 public class UniprotTest
51 {
52
53   @BeforeClass(alwaysRun = true)
54   public void setUpJvOptionPane()
55   {
56     JvOptionPane.setInteractiveMode(false);
57     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
58   }
59
60   // adapted from http://www.uniprot.org/uniprot/A9CKP4.xml
61   private static final String UNIPROT_XML = "<?xml version='1.0' encoding='UTF-8'?>"
62           + "<uniprot xmlns=\"http://uniprot.org/uniprot\">"
63           + "<entry dataset=\"TrEMBL\" created=\"2008-01-15\" modified=\"2015-03-04\" version=\"38\">"
64           + "<accession>A9CKP4</accession>"
65           + "<accession>A9CKP5</accession>" + "<name>A9CKP4_AGRT5</name>"
66           + "<name>A9CKP4_AGRT6</name>"
67           + "<protein><recommendedName><fullName>Mitogen-activated protein kinase 13</fullName></recommendedName></protein>"
68           + "<dbReference type=\"PDB\" id=\"2FSQ\"><property type=\"method\" value=\"X-ray\"/><property type=\"resolution\" value=\"1.40\"/></dbReference>"
69           + "<dbReference type=\"PDBsum\" id=\"2FSR\"/>"
70           + "<dbReference type=\"EMBL\" id=\"AE007869\"><property type=\"protein sequence ID\" value=\"AAK85932.1\"/><property type=\"molecule type\" value=\"Genomic_DNA\"/></dbReference>"
71           + "<feature type=\"signal peptide\" evidence=\"7\"><location><begin position=\"1\"/><end position=\"18\"/></location></feature>"
72           + "<feature type=\"propeptide\" description=\"Activation peptide\" id=\"PRO_0000027399\" evidence=\"9 16 17 18\"><location><begin position=\"19\"/><end position=\"20\"/></location></feature>"
73           + "<feature type=\"chain\" description=\"Granzyme B\" id=\"PRO_0000027400\"><location><begin position=\"21\"/><end position=\"247\"/></location></feature>"
74           + "<feature type=\"sequence variant\"><original>M</original><variation>L</variation><location><position position=\"41\"/></location></feature>"
75           + "<feature type=\"sequence variant\" description=\"Pathogenic\"><original>M</original><variation>L</variation><location><position position=\"41\"/></location></feature>"
76           + "<feature type=\"sequence variant\" description=\"Pathogenic\"><original>M</original><location><position position=\"41\"/></location></feature>"
77           + "<feature type=\"sequence variant\" description=\"Foo\"><variation>L</variation><variation>LMV</variation><original>M</original><location><position position=\"42\"/></location></feature>"
78           + "<feature type=\"sequence variant\" description=\"Foo\"><variation>LL</variation><variation>LMV</variation><original>ML</original><location><begin position=\"42\"/><end position=\"43\"/></location></feature>"
79           + "<feature type=\"sequence variant\" description=\"Foo Too\"><variation>LL</variation><variation>LMVK</variation><original>MLML</original><location><begin position=\"42\"/><end position=\"45\"/></location></feature>"
80           + "<sequence length=\"10\" mass=\"27410\" checksum=\"8CB760AACF88FE6C\" modified=\"2008-01-15\" version=\"1\">MHAPL VSKDL</sequence></entry>"
81           + "</uniprot>";
82
83   /**
84    * Test the method that unmarshals XML to a Uniprot model
85    * 
86    * @throws UnsupportedEncodingException
87    */
88   @Test(groups = { "Functional" })
89   public void testGetUniprotEntries() throws UnsupportedEncodingException
90   {
91     Uniprot u = new Uniprot();
92     InputStream is = new ByteArrayInputStream(UNIPROT_XML.getBytes());
93     List<Entry> entries = u.getUniprotEntries(is);
94     assertEquals(1, entries.size());
95     Entry entry = entries.get(0);
96     assertEquals(2, entry.getName().size());
97     assertEquals("A9CKP4_AGRT5", entry.getName().get(0));
98     assertEquals("A9CKP4_AGRT6", entry.getName().get(1));
99     assertEquals(2, entry.getAccession().size());
100     assertEquals("A9CKP4", entry.getAccession().get(0));
101     assertEquals("A9CKP5", entry.getAccession().get(1));
102
103     assertEquals("MHAPL VSKDL", entry.getSequence().getValue());
104
105     assertEquals("Mitogen-activated protein kinase 13", entry.getProtein()
106             .getRecommendedName().getFullName().getValue());
107
108     /*
109      * Check sequence features
110      */
111     List<FeatureType> features = entry.getFeature();
112     assertEquals(9, features.size());
113     FeatureType sf = features.get(0);
114     assertEquals("signal peptide", sf.getType());
115     assertNull(sf.getDescription());
116     assertNull(sf.getStatus());
117     assertNull(sf.getLocation().getPosition());
118     assertEquals(1, sf.getLocation().getBegin().getPosition().intValue());
119     assertEquals(18, sf.getLocation().getEnd().getPosition().intValue());
120     sf = features.get(1);
121     assertEquals("propeptide", sf.getType());
122     assertEquals("Activation peptide", sf.getDescription());
123     assertNull(sf.getLocation().getPosition());
124     assertEquals(19, sf.getLocation().getBegin().getPosition().intValue());
125     assertEquals(20, sf.getLocation().getEnd().getPosition().intValue());
126     sf = features.get(2);
127     assertEquals("chain", sf.getType());
128     assertEquals("Granzyme B", sf.getDescription());
129     assertNull(sf.getLocation().getPosition());
130     assertEquals(21, sf.getLocation().getBegin().getPosition().intValue());
131     assertEquals(247, sf.getLocation().getEnd().getPosition().intValue());
132
133     sf = features.get(3);
134     assertEquals("sequence variant", sf.getType());
135     assertNull(sf.getDescription());
136     assertEquals(41,
137             sf.getLocation().getPosition().getPosition().intValue());
138     assertNull(sf.getLocation().getBegin());
139     assertNull(sf.getLocation().getEnd());
140
141     sf = features.get(4);
142     assertEquals("sequence variant", sf.getType());
143     assertEquals("Pathogenic", sf.getDescription());
144     assertEquals(41,
145             sf.getLocation().getPosition().getPosition().intValue());
146     assertNull(sf.getLocation().getBegin());
147     assertNull(sf.getLocation().getEnd());
148
149     sf = features.get(5);
150     assertEquals("sequence variant", sf.getType());
151     assertEquals("Pathogenic", sf.getDescription());
152     assertEquals(41,
153             sf.getLocation().getPosition().getPosition().intValue());
154     assertNull(sf.getLocation().getBegin());
155     assertNull(sf.getLocation().getEnd());
156
157     sf = features.get(6);
158     assertEquals("sequence variant", sf.getType());
159     assertEquals("Foo", sf.getDescription());
160     assertEquals(42,
161             sf.getLocation().getPosition().getPosition().intValue());
162     assertNull(sf.getLocation().getBegin());
163     assertNull(sf.getLocation().getEnd());
164     Assert.assertEquals(Uniprot.getDescription(sf), "<html>p.Met42Leu"
165             + "<br/>&nbsp;&nbsp;" + "p.Met42LeuMetVal Foo</html>");
166
167     sf = features.get(7);
168     assertNull(sf.getLocation().getPosition());
169     assertEquals(42, sf.getLocation().getBegin().getPosition().intValue());
170     assertEquals(43, sf.getLocation().getEnd().getPosition().intValue());
171     Assert.assertEquals(Uniprot.getDescription(sf), "<html>p.MetLeu42LeuLeu"
172             + "<br/>&nbsp;&nbsp;" + "p.MetLeu42LeuMetVal Foo</html>");
173
174     sf = features.get(8);
175     assertNull(sf.getLocation().getPosition());
176     assertEquals(42, sf.getLocation().getBegin().getPosition().intValue());
177     assertEquals(45, sf.getLocation().getEnd().getPosition().intValue());
178     Assert.assertEquals(Uniprot.getDescription(sf), "<html>p.MLML42LeuLeu"
179             + "<br/>&nbsp;&nbsp;" + "p.MLML42LMVK Foo Too</html>");
180
181     /*
182      * Check cross-references
183      */
184     List<DbReferenceType> xrefs = entry.getDbReference();
185     assertEquals(3, xrefs.size());
186
187     DbReferenceType xref = xrefs.get(0);
188     assertEquals("2FSQ", xref.getId());
189     assertEquals("PDB", xref.getType());
190     assertEquals("X-ray",
191             Uniprot.getProperty(xref.getProperty(), "method"));
192     assertEquals("1.40",
193             Uniprot.getProperty(xref.getProperty(), "resolution"));
194
195     xref = xrefs.get(1);
196     assertEquals("2FSR", xref.getId());
197     assertEquals("PDBsum", xref.getType());
198     assertTrue(xref.getProperty().isEmpty());
199
200     xref = xrefs.get(2);
201     assertEquals("AE007869", xref.getId());
202     assertEquals("EMBL", xref.getType());
203     assertEquals("AAK85932.1",
204             Uniprot.getProperty(xref.getProperty(), "protein sequence ID"));
205     assertEquals("Genomic_DNA",
206             Uniprot.getProperty(xref.getProperty(), "molecule type"));
207   }
208
209   @Test(groups = { "Functional" })
210   public void testGetUniprotSequence() throws UnsupportedEncodingException
211   {
212     InputStream is = new ByteArrayInputStream(UNIPROT_XML.getBytes());
213     Entry entry = new Uniprot().getUniprotEntries(is).get(0);
214     SequenceI seq = new Uniprot().uniprotEntryToSequence(entry);
215     assertNotNull(seq);
216     assertEquals(6, seq.getDBRefs().size()); // 2*Uniprot, PDB, PDBsum, 2*EMBL
217     assertEquals(seq.getSequenceAsString(),
218             seq.createDatasetSequence().getSequenceAsString());
219     assertEquals(2, seq.getPrimaryDBRefs().size());
220     List<DBRefEntry> res = DBRefUtils.searchRefs(seq.getPrimaryDBRefs(),
221             "A9CKP4");
222     assertEquals(1, res.size());
223     assertTrue(res.get(0).isCanonical());
224     res = DBRefUtils.searchRefsForSource(seq.getDBRefs(),
225             DBRefSource.UNIPROT);
226     assertEquals(2, res.size());
227     res = DBRefUtils.searchRefs(seq.getDBRefs(), "AAK85932");
228     assertEquals(1, res.size());
229     assertTrue("1".equals(res.get(0).getVersion()));
230     /*
231      * NB this test fragile - relies on ordering being preserved
232      */
233     assertTrue(res.get(0).isCanonical());
234     assertFalse(res.get(1).isCanonical());
235
236     // check version is preserved for EMBLCDS
237     res = DBRefUtils.searchRefs(seq.getDBRefs(), "AAK85932");
238     assertEquals(1, res.size());
239     // Ideally we would expect AAK85932.1 -> AAK85932
240     // assertTrue("1".equals(res.get(0).getVersion()));
241     // but it also passes through DBrefUtils.ensurePrimaries which adds
242     // (promoted) to the version string
243     // FIXME: Jim needs to specify what (promoted) means !! - or perhaps we just
244     // ignore it !
245     assertEquals("1 (promoted)", (res.get(0).getVersion()));
246   }
247
248   /**
249    * Test the method that formats the sequence id
250    * 
251    * @throws UnsupportedEncodingException
252    */
253   @Test(groups = { "Functional" })
254   public void testGetUniprotEntryId() throws UnsupportedEncodingException
255   {
256     InputStream is = new ByteArrayInputStream(UNIPROT_XML.getBytes());
257     Entry entry = new Uniprot().getUniprotEntries(is).get(0);
258
259     /*
260      * name formatted with Uniprot Entry name
261      */
262     String expectedName = "A9CKP4_AGRT5|A9CKP4_AGRT6";
263     assertEquals(expectedName, Uniprot.getUniprotEntryId(entry));
264   }
265
266   /**
267    * Test the method that formats the sequence description
268    * 
269    * @throws UnsupportedEncodingException
270    */
271   @Test(groups = { "Functional" })
272   public void testGetUniprotEntryDescription()
273           throws UnsupportedEncodingException
274   {
275     InputStream is = new ByteArrayInputStream(UNIPROT_XML.getBytes());
276     Entry entry = new Uniprot().getUniprotEntries(is).get(0);
277
278     assertEquals("Mitogen-activated protein kinase 13",
279             Uniprot.getUniprotEntryDescription(entry));
280   }
281
282   @Test(groups = { "Functional" })
283   public void testGetDescription()
284   {
285     FeatureType ft = new FeatureType();
286     assertEquals("", Uniprot.getDescription(ft));
287
288     ft.setDescription("Hello");
289     assertEquals("Hello", Uniprot.getDescription(ft));
290
291     ft.setLocation(new LocationType());
292     ft.getLocation().setPosition(new PositionType());
293     ft.getLocation().getPosition().setPosition(BigInteger.valueOf(23));
294     ft.setOriginal("K");
295     ft.getVariation().add("y");
296     assertEquals("p.Lys23Tyr Hello", Uniprot.getDescription(ft));
297
298     // multiple variants generate an html description over more than one line
299     ft.getVariation().add("W");
300     assertEquals("<html>p.Lys23Tyr<br/>&nbsp;&nbsp;p.Lys23Trp Hello</html>",
301             Uniprot.getDescription(ft));
302
303     /*
304      * indel cases
305      * up to 3 bases (original or variant) are shown using 3 letter code
306      */
307     ft.getVariation().clear();
308     ft.getVariation().add("KWE");
309     ft.setOriginal("KLS");
310     assertEquals("p.LysLeuSer23LysTrpGlu Hello",
311             Uniprot.getDescription(ft));
312
313     // adding a fourth original base switches to single letter code
314     ft.setOriginal("KLST");
315     assertEquals("p.KLST23LysTrpGlu Hello", Uniprot.getDescription(ft));
316
317     // adding a fourth variant switches to single letter code
318     ft.getVariation().clear();
319     ft.getVariation().add("KWES");
320     assertEquals("p.KLST23KWES Hello", Uniprot.getDescription(ft));
321
322     ft.getVariation().clear();
323     ft.getVariation().add("z"); // unknown variant - fails gracefully
324     ft.setOriginal("K");
325     assertEquals("p.Lys23z Hello", Uniprot.getDescription(ft));
326
327     ft.getVariation().clear(); // variant missing - is ignored
328     assertEquals("Hello", Uniprot.getDescription(ft));
329   }
330 }