JAL-2629 add option to set HMM Logo letter height to info content
[jalview.git] / test / jalview / analysis / AAFrequencyTest.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.analysis;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertNull;
25
26 import jalview.datamodel.AlignmentAnnotation;
27 import jalview.datamodel.Annotation;
28 import jalview.datamodel.HiddenMarkovModel;
29 import jalview.datamodel.Profile;
30 import jalview.datamodel.ProfileI;
31 import jalview.datamodel.Profiles;
32 import jalview.datamodel.ProfilesI;
33 import jalview.datamodel.Sequence;
34 import jalview.datamodel.SequenceI;
35 import jalview.gui.JvOptionPane;
36 import jalview.io.DataSourceType;
37 import jalview.io.FileParse;
38 import jalview.io.HMMFile;
39
40 import java.io.IOException;
41 import java.net.MalformedURLException;
42
43 import org.testng.annotations.BeforeClass;
44 import org.testng.annotations.Test;
45
46 public class AAFrequencyTest
47 {
48
49   HiddenMarkovModel hmm;
50
51   @BeforeClass(alwaysRun = true)
52   public void setUpJvOptionPane()
53   {
54     JvOptionPane.setInteractiveMode(false);
55     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
56   }
57
58   @Test(groups = { "Functional" })
59   public void testCalculate_noProfile()
60   {
61     SequenceI seq1 = new Sequence("Seq1", "CAG-T");
62     SequenceI seq2 = new Sequence("Seq2", "CAC-T");
63     SequenceI seq3 = new Sequence("Seq3", "C---G");
64     SequenceI seq4 = new Sequence("Seq4", "CA--t");
65     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
66     int width = seq1.getLength();
67     ProfilesI result = AAFrequency.calculate(seqs, width, 0, width,
68             false);
69
70     // col 0 is 100% C
71     ProfileI col = result.get(0);
72     assertEquals(100f, col.getPercentageIdentity(false));
73     assertEquals(100f, col.getPercentageIdentity(true));
74     assertEquals(4, col.getMaxCount());
75     assertEquals("C", col.getModalResidue());
76     assertNull(col.getCounts());
77
78     // col 1 is 75% A
79     col = result.get(1);
80     assertEquals(75f, col.getPercentageIdentity(false));
81     assertEquals(100f, col.getPercentageIdentity(true));
82     assertEquals(3, col.getMaxCount());
83     assertEquals("A", col.getModalResidue());
84
85     // col 2 is 50% G 50% C or 25/25 counting gaps
86     col = result.get(2);
87     assertEquals(25f, col.getPercentageIdentity(false));
88     assertEquals(50f, col.getPercentageIdentity(true));
89     assertEquals(1, col.getMaxCount());
90     assertEquals("CG", col.getModalResidue());
91
92     // col 3 is all gaps
93     col = result.get(3);
94     assertEquals(0f, col.getPercentageIdentity(false));
95     assertEquals(0f, col.getPercentageIdentity(true));
96     assertEquals(0, col.getMaxCount());
97     assertEquals("", col.getModalResidue());
98
99     // col 4 is 75% T 25% G
100     col = result.get(4);
101     assertEquals(75f, col.getPercentageIdentity(false));
102     assertEquals(75f, col.getPercentageIdentity(true));
103     assertEquals(3, col.getMaxCount());
104     assertEquals("T", col.getModalResidue());
105   }
106
107   @Test(groups = { "Functional" })
108   public void testCalculate_withProfile()
109   {
110     SequenceI seq1 = new Sequence("Seq1", "CAGT");
111     SequenceI seq2 = new Sequence("Seq2", "CACT");
112     SequenceI seq3 = new Sequence("Seq3", "C--G");
113     SequenceI seq4 = new Sequence("Seq4", "CA-t");
114     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
115     int width = seq1.getLength();
116     ProfilesI result = AAFrequency.calculate(seqs, width, 0, width,
117             true);
118
119     ProfileI profile = result.get(0);
120     assertEquals(4, profile.getCounts().getCount('C'));
121     assertEquals(4, profile.getHeight());
122     assertEquals(4, profile.getNonGapped());
123
124     profile = result.get(1);
125     assertEquals(3, profile.getCounts().getCount('A'));
126     assertEquals(4, profile.getHeight());
127     assertEquals(3, profile.getNonGapped());
128
129     profile = result.get(2);
130     assertEquals(1, profile.getCounts().getCount('C'));
131     assertEquals(1, profile.getCounts().getCount('G'));
132     assertEquals(4, profile.getHeight());
133     assertEquals(2, profile.getNonGapped());
134
135     profile = result.get(3);
136     assertEquals(3, profile.getCounts().getCount('T'));
137     assertEquals(1, profile.getCounts().getCount('G'));
138     assertEquals(4, profile.getHeight());
139     assertEquals(4, profile.getNonGapped());
140   }
141
142   @Test(groups = { "Functional" }, enabled = false)
143   public void testCalculate_withProfileTiming()
144   {
145     SequenceI seq1 = new Sequence("Seq1", "CAGT");
146     SequenceI seq2 = new Sequence("Seq2", "CACT");
147     SequenceI seq3 = new Sequence("Seq3", "C--G");
148     SequenceI seq4 = new Sequence("Seq4", "CA-t");
149     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
150
151     // ensure class loaded and initialised
152     int width = seq1.getLength();
153     AAFrequency.calculate(seqs, width, 0, width, true);
154
155     int reps = 100000;
156     long start = System.currentTimeMillis();
157     for (int i = 0; i < reps; i++)
158     {
159       AAFrequency.calculate(seqs, width, 0, width, true);
160     }
161     System.out.println(System.currentTimeMillis() - start);
162   }
163
164   /**
165    * Test generation of consensus annotation with options 'include gaps'
166    * (profile percentages are of all sequences, whether gapped or not), and
167    * 'show logo' (the full profile with all residue percentages is reported in
168    * the description for the tooltip)
169    */
170   @Test(groups = { "Functional" })
171   public void testCompleteConsensus_includeGaps_showLogo()
172   {
173     /*
174      * first compute the profiles
175      */
176     SequenceI seq1 = new Sequence("Seq1", "CAG-T");
177     SequenceI seq2 = new Sequence("Seq2", "CAC-T");
178     SequenceI seq3 = new Sequence("Seq3", "C---G");
179     SequenceI seq4 = new Sequence("Seq4", "CA--t");
180     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
181     int width = seq1.getLength();
182     ProfilesI profiles = AAFrequency.calculate(seqs, width, 0, width, true);
183
184     AlignmentAnnotation consensus = new AlignmentAnnotation("Consensus",
185             "PID", new Annotation[width]);
186     AAFrequency
187             .completeConsensus(consensus, profiles, 0, 5, false, true, 4);
188
189     Annotation ann = consensus.annotations[0];
190     assertEquals("C 100%", ann.description);
191     assertEquals("C", ann.displayCharacter);
192     ann = consensus.annotations[1];
193     assertEquals("A 75%", ann.description);
194     assertEquals("A", ann.displayCharacter);
195     ann = consensus.annotations[2];
196     assertEquals("C 25%; G 25%", ann.description);
197     assertEquals("+", ann.displayCharacter);
198     ann = consensus.annotations[3];
199     assertEquals("", ann.description);
200     assertEquals("-", ann.displayCharacter);
201     ann = consensus.annotations[4];
202     assertEquals("T 75%; G 25%", ann.description);
203     assertEquals("T", ann.displayCharacter);
204   }
205
206   /**
207    * Test generation of consensus annotation with options 'ignore gaps' (profile
208    * percentages are of the non-gapped sequences) and 'no logo' (only the modal
209    * residue[s] percentage is reported in the description for the tooltip)
210    */
211   @Test(groups = { "Functional" })
212   public void testCompleteConsensus_ignoreGaps_noLogo()
213   {
214     /*
215      * first compute the profiles
216      */
217     SequenceI seq1 = new Sequence("Seq1", "CAG-T");
218     SequenceI seq2 = new Sequence("Seq2", "CAC-T");
219     SequenceI seq3 = new Sequence("Seq3", "C---G");
220     SequenceI seq4 = new Sequence("Seq4", "CA--t");
221     SequenceI[] seqs = new SequenceI[] { seq1, seq2, seq3, seq4 };
222     int width = seq1.getLength();
223     ProfilesI profiles = AAFrequency.calculate(seqs, width, 0, width, true);
224   
225     AlignmentAnnotation consensus = new AlignmentAnnotation("Consensus",
226             "PID", new Annotation[width]);
227     AAFrequency
228             .completeConsensus(consensus, profiles, 0, 5, true, false, 4);
229   
230     Annotation ann = consensus.annotations[0];
231     assertEquals("C 100%", ann.description);
232     assertEquals("C", ann.displayCharacter);
233     ann = consensus.annotations[1];
234     assertEquals("A 100%", ann.description);
235     assertEquals("A", ann.displayCharacter);
236     ann = consensus.annotations[2];
237     assertEquals("[CG] 50%", ann.description);
238     assertEquals("+", ann.displayCharacter);
239     ann = consensus.annotations[3];
240     assertEquals("", ann.description);
241     assertEquals("-", ann.displayCharacter);
242     ann = consensus.annotations[4];
243     assertEquals("T 75%", ann.description);
244     assertEquals("T", ann.displayCharacter);
245   }
246
247
248   @Test(groups = { "Functional" }, priority = 1)
249   public void testExtractHMMProfile()
250           throws MalformedURLException, IOException
251   {
252   
253     HMMFile hmmFile = new HMMFile(new FileParse(
254             "test/jalview/io/test_MADE1_hmm.txt", DataSourceType.FILE));
255     hmm = hmmFile.getHMM();
256     int[] expected = { 0, 4, 100, 'T', 71, 'C', 12, 'G', 9, 'A', 9 };
257     int[] actual = AAFrequency.extractHMMProfile(hmm, 17, false, false);
258     for (int i = 0; i < actual.length; i++)
259     {
260       if (i == 2)
261       {
262         assertEquals(actual[i], expected[i]);
263       }
264       else
265       {
266         assertEquals(actual[i], expected[i]);
267       }
268     }
269   
270     int[] expected2 = { 0, 4, 100, 'A', 85, 'C', 0, 'G', 0, 'T', 0 };
271     int[] actual2 = AAFrequency.extractHMMProfile(hmm, 2, true, false);
272     for (int i = 0; i < actual2.length; i++)
273     {
274       if (i == 2)
275       {
276         assertEquals(actual[i], expected[i]);
277       }
278       else
279       {
280         assertEquals(actual[i], expected[i]);
281       }
282     }
283
284     assertNull(AAFrequency.extractHMMProfile(null, 98978867, true, false));
285   }
286
287   @Test(groups = { "Functional" }, priority = 2)
288   public void testGetAnalogueCount()
289   {
290     int count;
291     count = AAFrequency.getAnalogueCount(hmm, 0, 'T', false, false);
292     assertEquals(7859, count);
293     count = AAFrequency.getAnalogueCount(hmm, 20, 'G', false, false);
294     assertEquals(7546, count);
295     count = AAFrequency.getAnalogueCount(hmm, 1077, 'G', true, false);
296     assertEquals(0, count);
297   }
298
299   @Test(groups = { "Functional" }, priority = 3)
300   public void testCompleteInformation()
301   {
302     ProfileI prof1 = new Profile(1, 0, 100, "A");
303     ProfileI prof2 = new Profile(1, 0, 100, "-");
304
305     ProfilesI profs = new Profiles(new ProfileI[] { prof1, prof2 });
306     Annotation ann1 = new Annotation(6.5f);
307     Annotation ann2 = new Annotation(0f);
308     Annotation[] annots = new Annotation[] { ann1, ann2 };
309     SequenceI seq = new Sequence("", "AA", 0, 0);
310     seq.setHMM(hmm);
311     AlignmentAnnotation annot = new AlignmentAnnotation("", "", annots);
312     annot.setSequenceRef(seq);
313     AAFrequency.completeInformation(annot, profs, 0, 1, 1, 1f);
314     float ic = annot.annotations[0].value;
315     assertEquals(0.91532f, ic, 0.0001f);
316     ic = annot.annotations[1].value;
317     assertEquals(0f, ic, 0.0001f);
318     int i = 0;
319   }
320
321 }