Merge branch 'develop' into features/JAL-2110_makeSenseOfCrossRef
[jalview.git] / test / jalview / analysis / CrossRefsTest.java
1 package jalview.analysis;
2
3 import static org.testng.AssertJUnit.assertEquals;
4 import static org.testng.AssertJUnit.assertNotSame;
5 import static org.testng.AssertJUnit.assertNull;
6 import static org.testng.AssertJUnit.assertSame;
7 import static org.testng.internal.junit.ArrayAsserts.assertArrayEquals;
8
9 import jalview.datamodel.Alignment;
10 import jalview.datamodel.AlignmentI;
11 import jalview.datamodel.DBRefEntry;
12 import jalview.datamodel.Mapping;
13 import jalview.datamodel.Sequence;
14 import jalview.datamodel.SequenceFeature;
15 import jalview.datamodel.SequenceI;
16 import jalview.util.MapList;
17 import jalview.ws.SequenceFetcher;
18 import jalview.ws.SequenceFetcherFactory;
19
20 import java.util.List;
21
22 import org.testng.annotations.Test;
23
24 public class CrossRefsTest
25 {
26
27   /**
28    * Test for finding 'product' sequences for the case where the selected
29    * sequence has a dbref with a mapping to a sequence
30    */
31   @Test(groups = { "Functional" })
32   public void testFindXrefSequences_fromDbRefMap()
33   {
34     /*
35      * two peptide sequences each with a DBRef and SequenceFeature
36      */
37     SequenceI pep1 = new Sequence("Q9ZTS2", "MALFQRSV");
38     pep1.addDBRef(new DBRefEntry("Pfam", "0", "PF00111"));
39     pep1.addSequenceFeature(new SequenceFeature("type", "desc", 12, 14, 1f,
40             "group"));
41     SequenceI pep2 = new Sequence("P30419", "MTRRSQIF");
42     pep2.addDBRef(new DBRefEntry("PDB", "0", "3JTK"));
43     pep2.addSequenceFeature(new SequenceFeature("type2", "desc2", 13, 15,
44             12f, "group2"));
45   
46     /*
47      * nucleotide sequence (to go in the alignment)
48      */
49     SequenceI dna1 = new Sequence("AF039662", "GGGGCAGCACAAGAAC");
50   
51     /*
52      * add DBRefEntry's to dna1 with mappings from dna to both peptides
53      */
54     MapList mapList = new MapList(new int[] { 1, 24 }, new int[] { 1, 3 },
55             3, 1);
56     Mapping map = new Mapping(pep1, mapList);
57     DBRefEntry dbRef1 = new DBRefEntry("UNIPROT", "0", "Q9ZTS2", map);
58     dna1.addDBRef(dbRef1);
59     mapList = new MapList(new int[] { 1, 24 }, new int[] { 1, 3 }, 3, 1);
60     map = new Mapping(pep2, mapList);
61     DBRefEntry dbRef2 = new DBRefEntry("UNIPROT", "0", "P30419", map);
62     dna1.addDBRef(dbRef2);
63   
64     /*
65      * find UNIPROT xrefs for nucleotide sequence - it should pick up 
66      * mapped sequences
67      */
68     AlignmentI al = new Alignment(new SequenceI[] { dna1 });
69     AlignmentI xrefs = CrossRefs.findXrefSequences(
70             new SequenceI[] { dna1 },
71             true, "UNIPROT", al);
72     assertEquals(2, xrefs.getHeight());
73   
74     /*
75      * cross-refs alignment holds copies of the mapped sequences
76      * including copies of their dbrefs and features
77      */
78     checkCopySequence(pep1, xrefs.getSequenceAt(0));
79     checkCopySequence(pep2, xrefs.getSequenceAt(1));
80   }
81
82   /**
83    * Test for finding 'product' sequences for the case where only an indirect
84    * xref is found - not on the peptide sequence but on a nucleotide sequence in
85    * the alignment which which it shares a protein dbref
86    */
87   @Test(groups = { "Functional" })
88   public void testFindXrefSequences_indirectDbrefToNucleotide()
89   {
90     /*
91      * Alignment setup:
92      *   - peptide    dbref  UNIPROT|Q9ZTS2
93      *   - nucleotide dbref  EMBL|AF039662, UNIPROT|Q9ZTS2
94      */
95     SequenceI uniprotSeq = new Sequence("Q9ZTS2", "MASVSATMISTS");
96     uniprotSeq.addDBRef(new DBRefEntry("UNIPROT", "0", "Q9ZTS2"));
97     SequenceI emblSeq = new Sequence("AF039662", "GGGGCAGCACAAGAAC");
98     emblSeq.addDBRef(new DBRefEntry("EMBL", "0", "AF039662"));
99     emblSeq.addDBRef(new DBRefEntry("UNIPROT", "0", "Q9ZTS2"));
100   
101     /*
102      * find EMBL xrefs for peptide sequence - it has no direct
103      * dbrefs, but the 'corresponding' nucleotide sequence does, so is returned
104      */
105     /*
106      * Find EMBL xrefs for peptide 
107      * - it has no EMBL dbref of its own
108      * - but nucleotide with matching peptide dbref does, so is returned
109      */
110     AlignmentI al = new Alignment(new SequenceI[] { emblSeq, uniprotSeq });
111     AlignmentI xrefs = CrossRefs.findXrefSequences(
112             new SequenceI[] { uniprotSeq }, false, "EMBL", al);
113     assertEquals(1, xrefs.getHeight());
114     assertSame(emblSeq, xrefs.getSequenceAt(0));
115   }
116
117   /**
118    * Test for finding 'product' sequences for the case where only an indirect
119    * xref is found - not on the nucleotide sequence but on a peptide sequence in
120    * the alignment which which it shares a nucleotide dbref
121    */
122   @Test(groups = { "Functional" })
123   public void testFindXrefSequences_indirectDbrefToProtein()
124   {
125     /*
126      * Alignment setup:
127      *   - nucleotide dbref  EMBL|AF039662
128      *   - peptide    dbrefs EMBL|AF039662, UNIPROT|Q9ZTS2
129      */
130     SequenceI emblSeq = new Sequence("AF039662", "GGGGCAGCACAAGAAC");
131     emblSeq.addDBRef(new DBRefEntry("EMBL", "0", "AF039662"));
132     SequenceI uniprotSeq = new Sequence("Q9ZTS2", "MASVSATMISTS");
133     uniprotSeq.addDBRef(new DBRefEntry("EMBL", "0", "AF039662"));
134     uniprotSeq.addDBRef(new DBRefEntry("UNIPROT", "0", "Q9ZTS2"));
135   
136     /*
137      * Find UNIPROT xrefs for nucleotide 
138      * - it has no UNIPROT dbref of its own
139      * - but peptide with matching nucleotide dbref does, so is returned
140      */
141     AlignmentI al = new Alignment(new SequenceI[] { emblSeq, uniprotSeq });
142     AlignmentI xrefs = CrossRefs.findXrefSequences(
143             new SequenceI[] { emblSeq }, true, "UNIPROT", al);
144     assertEquals(1, xrefs.getHeight());
145     assertSame(uniprotSeq, xrefs.getSequenceAt(0));
146   }
147
148   /**
149    * Test for finding 'product' sequences for the case where the selected
150    * sequence has no dbref to the desired source, and there are no indirect
151    * references via another sequence in the alignment
152    */
153   @Test(groups = { "Functional" })
154   public void testFindXrefSequences_noDbrefs()
155   {
156     /*
157      * two nucleotide sequences, one with UNIPROT dbref
158      */
159     SequenceI dna1 = new Sequence("AF039662", "GGGGCAGCACAAGAAC");
160     dna1.addDBRef(new DBRefEntry("UNIPROT", "0", "Q9ZTS2"));
161     SequenceI dna2 = new Sequence("AJ307031", "AAACCCTTT");
162   
163     /*
164      * find UNIPROT xrefs for peptide sequence - it has no direct
165      * dbrefs, and the other sequence (which has a UNIPROT dbref) is not 
166      * equatable to it, so no results found
167      */
168     AlignmentI al = new Alignment(new SequenceI[] { dna1, dna2 });
169     AlignmentI xrefs = CrossRefs.findXrefSequences(
170             new SequenceI[] { dna2 },
171             true, "UNIPROT", al);
172     assertNull(xrefs);
173   }
174
175   /**
176    * Test for finding 'product' sequences for the case where the selected
177    * sequence has a dbref with no mapping, triggering a fetch from database
178    */
179   @Test(groups = { "Functional" })
180   public void testFindXrefSequences_withFetch()
181   {
182     SequenceI dna1 = new Sequence("AF039662", "GGGGCAGCACAAGAAC");
183     dna1.addDBRef(new DBRefEntry("UNIPROT", "0", "Q9ZTS2"));
184     dna1.addDBRef(new DBRefEntry("UNIPROT", "0", "P30419"));
185     dna1.addDBRef(new DBRefEntry("UNIPROT", "0", "P00314"));
186     final SequenceI pep1 = new Sequence("Q9ZTS2", "MYQLIRSSW");
187     final SequenceI pep2 = new Sequence("P00314", "MRKLLAASG");
188   
189     SequenceFetcher mockFetcher = new SequenceFetcher()
190     {
191   
192       @Override
193       public boolean isFetchable(String source)
194       {
195         return true;
196       }
197   
198       @Override
199       public SequenceI[] getSequences(List<DBRefEntry> refs, boolean dna)
200       {
201         return new SequenceI[] { pep1, pep2 };
202       }
203     };
204     SequenceFetcherFactory.setSequenceFetcher(mockFetcher);
205   
206     /*
207      * find UNIPROT xrefs for nucleotide sequence
208      */
209     AlignmentI al = new Alignment(new SequenceI[] { dna1 });
210     AlignmentI xrefs = CrossRefs.findXrefSequences(
211             new SequenceI[] { dna1 },
212             true, "UNIPROT", al);
213     assertEquals(2, xrefs.getHeight());
214     assertSame(pep1, xrefs.getSequenceAt(0));
215     assertSame(pep2, xrefs.getSequenceAt(1));
216   }
217
218   /**
219    * Helper method to assert seq1 looks like a copy of seq2
220    * 
221    * @param seq1
222    * @param seq2
223    */
224   private void checkCopySequence(SequenceI seq1, SequenceI seq2)
225   {
226     assertNotSame(seq1, seq2);
227     assertEquals(seq1.getName(), seq2.getName());
228     assertEquals(seq1.getStart(), seq2.getStart());
229     assertEquals(seq1.getEnd(), seq2.getEnd());
230     assertEquals(seq1.getSequenceAsString(), seq2.getSequenceAsString());
231   
232     /*
233      * compare dbrefs
234      */
235     assertArrayEquals(seq1.getDBRefs(), seq2.getDBRefs());
236     // check one to verify a copy, not the same object
237     if (seq1.getDBRefs().length > 0)
238     {
239       assertNotSame(seq1.getDBRefs()[0], seq2.getDBRefs()[0]);
240     }
241   
242     /*
243      * compare features
244      */
245     assertArrayEquals(seq1.getSequenceFeatures(),
246             seq2.getSequenceFeatures());
247     if (seq1.getSequenceFeatures().length > 0)
248     {
249       assertNotSame(seq1.getSequenceFeatures()[0],
250               seq2.getSequenceFeatures()[0]);
251     }
252   }
253
254   /**
255    * Test for finding 'product' sequences for the case where the selected
256    * sequence has two dbrefs with no mapping, triggering a fetch from database.
257    * 
258    * @see http://issues.jalview.org/browse/JAL-2029
259    */
260   @Test(groups = { "Functional" })
261   public void testFindXrefSequences_withFetchMultipleRefs()
262   {
263     /*
264      * EMBL|X07547 has a 
265      */
266     SequenceI dna1 = new Sequence("X07547", "GGGGCAGCACAAGAAC");
267     dna1.addDBRef(new DBRefEntry("UNIPROT", "0", "B0BCM4"));
268     dna1.addDBRef(new DBRefEntry("UNIPROT", "0", "P0CE20"));
269     final SequenceI pep1 = new Sequence("B0BCM4", "MGKGIL");
270     final SequenceI pep2 = new Sequence("P0CE20", "MGKGIL");
271   
272     SequenceFetcher mockFetcher = new SequenceFetcher()
273     {
274       int call = 0;
275
276       @Override
277       public boolean isFetchable(String source)
278       {
279         return true;
280       }
281       @Override
282       public SequenceI[] getSequences(List<DBRefEntry> refs, boolean dna)
283       {
284         // pending Mockito with its thenReturn(pep1).thenReturn(pep2) syntax!
285         return new SequenceI[] { call++ == 0 ? pep1 : pep2 };
286       }
287     };
288     SequenceFetcherFactory.setSequenceFetcher(mockFetcher);
289   
290     /*
291      * find UNIPROT xrefs for nucleotide sequence
292      */
293     AlignmentI al = new Alignment(new SequenceI[] { dna1 });
294     AlignmentI xrefs = CrossRefs.findXrefSequences(
295             new SequenceI[] { dna1 },
296             true, "UNIPROT", al);
297     assertEquals(2, xrefs.getHeight());
298     assertSame(pep1, xrefs.getSequenceAt(0));
299     assertSame(pep2, xrefs.getSequenceAt(1));
300   }
301
302 }