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