JAL-3438 spotless for 2.11.2.0
[jalview.git] / test / jalview / analysis / ConservationTest.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.Assert.assertEquals;
24 import static org.testng.Assert.assertTrue;
25
26 import jalview.datamodel.Sequence;
27 import jalview.datamodel.SequenceI;
28 import jalview.gui.JvOptionPane;
29
30 import java.util.ArrayList;
31 import java.util.HashMap;
32 import java.util.List;
33 import java.util.Map;
34
35 import org.testng.annotations.BeforeClass;
36 import org.testng.annotations.Test;
37
38 public class ConservationTest
39 {
40
41   @BeforeClass(alwaysRun = true)
42   public void setUpJvOptionPane()
43   {
44     JvOptionPane.setInteractiveMode(false);
45     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
46   }
47
48   @Test(groups = "Functional")
49   public void testRecordConservation()
50   {
51     Map<String, Integer> resultMap = new HashMap<String, Integer>();
52
53     // V is hydrophobic, aliphatic, small
54     Conservation.recordConservation(resultMap, "V");
55     assertEquals(resultMap.get("hydrophobic").intValue(), 1);
56     assertEquals(resultMap.get("aliphatic").intValue(), 1);
57     assertEquals(resultMap.get("small").intValue(), 1);
58     assertEquals(resultMap.get("tiny").intValue(), 0);
59     assertEquals(resultMap.get("polar").intValue(), 0);
60     assertEquals(resultMap.get("charged").intValue(), 0);
61
62     // now add S: not hydrophobic, small, tiny, polar, not aliphatic
63     Conservation.recordConservation(resultMap, "s");
64     assertEquals(resultMap.get("hydrophobic").intValue(), -1);
65     assertEquals(resultMap.get("aliphatic").intValue(), -1);
66     assertEquals(resultMap.get("small").intValue(), 1);
67     assertEquals(resultMap.get("tiny").intValue(), -1);
68     assertEquals(resultMap.get("polar").intValue(), -1);
69     assertEquals(resultMap.get("charged").intValue(), 0);
70   }
71
72   @Test(groups = "Functional")
73   public void testCountConservationAndGaps()
74   {
75     List<SequenceI> seqs = new ArrayList<SequenceI>();
76     seqs.add(new Sequence("seq1", "VGnY")); // not case sensitive
77     seqs.add(new Sequence("seq2", "-G-y"));
78     seqs.add(new Sequence("seq3", "VG-Y"));
79     seqs.add(new Sequence("seq4", "VGNW"));
80
81     Conservation cons = new Conservation("", seqs, 0, 50);
82     int[] counts = cons.countConservationAndGaps(0);
83     assertEquals(counts[0], 1); // conserved
84     assertEquals(counts[1], 1); // gap count
85     counts = cons.countConservationAndGaps(1);
86     assertEquals(counts[0], 1);
87     assertEquals(counts[1], 0);
88     counts = cons.countConservationAndGaps(2);
89     assertEquals(counts[0], 1);
90     assertEquals(counts[1], 2);
91     counts = cons.countConservationAndGaps(3);
92     assertEquals(counts[0], 0); // not conserved
93     assertEquals(counts[1], 0);
94   }
95
96   @Test(groups = "Functional")
97   public void testCalculate_noThreshold()
98   {
99     List<SequenceI> seqs = new ArrayList<SequenceI>();
100     seqs.add(new Sequence("seq1", "VGIV-N"));
101     seqs.add(new Sequence("seq2", "V-iL-N")); // not case sensitive
102     seqs.add(new Sequence("seq3", "V-IW-N"));
103     seqs.add(new Sequence("seq4", "VGLH-L"));
104
105     Conservation cons = new Conservation("", 0, seqs, 0, 5);
106     cons.calculate();
107
108     /*
109      * column 0: all V (hydrophobic/aliphatic/small)
110      */
111     Map<String, Integer> colCons = cons.total[0];
112     assertEquals(colCons.get("hydrophobic").intValue(), 1);
113     assertEquals(colCons.get("aliphatic").intValue(), 1);
114     assertEquals(colCons.get("small").intValue(), 1);
115     assertEquals(colCons.get("tiny").intValue(), 0);
116     assertEquals(colCons.get("proline").intValue(), 0);
117     assertEquals(colCons.get("charged").intValue(), 0);
118     assertEquals(colCons.get("negative").intValue(), 0);
119     assertEquals(colCons.get("polar").intValue(), 0);
120     assertEquals(colCons.get("positive").intValue(), 0);
121     assertEquals(colCons.get("aromatic").intValue(), 0);
122
123     /*
124      * column 1: all G (hydrophobic/small/tiny)
125      * gaps take default value of property present
126      */
127     colCons = cons.total[1];
128     assertEquals(colCons.get("hydrophobic").intValue(), 1);
129     assertEquals(colCons.get("aliphatic").intValue(), -1);
130     assertEquals(colCons.get("small").intValue(), 1);
131     assertEquals(colCons.get("tiny").intValue(), 1);
132     assertEquals(colCons.get("proline").intValue(), -1);
133     assertEquals(colCons.get("charged").intValue(), -1);
134     assertEquals(colCons.get("negative").intValue(), -1);
135     assertEquals(colCons.get("polar").intValue(), -1);
136     assertEquals(colCons.get("positive").intValue(), -1);
137     assertEquals(colCons.get("aromatic").intValue(), -1);
138
139     /*
140      * column 2: I/L (aliphatic/hydrophobic), all others negatively conserved
141      */
142     colCons = cons.total[2];
143     assertEquals(colCons.get("hydrophobic").intValue(), 1);
144     assertEquals(colCons.get("aliphatic").intValue(), 1);
145     assertEquals(colCons.get("small").intValue(), 0);
146     assertEquals(colCons.get("tiny").intValue(), 0);
147     assertEquals(colCons.get("proline").intValue(), 0);
148     assertEquals(colCons.get("charged").intValue(), 0);
149     assertEquals(colCons.get("negative").intValue(), 0);
150     assertEquals(colCons.get("polar").intValue(), 0);
151     assertEquals(colCons.get("positive").intValue(), 0);
152     assertEquals(colCons.get("aromatic").intValue(), 0);
153
154     /*
155      * column 3: VLWH all hydrophobic, none is tiny, negative or proline
156      */
157     colCons = cons.total[3];
158     assertEquals(colCons.get("hydrophobic").intValue(), 1);
159     assertEquals(colCons.get("aliphatic").intValue(), -1);
160     assertEquals(colCons.get("small").intValue(), -1);
161     assertEquals(colCons.get("tiny").intValue(), 0);
162     assertEquals(colCons.get("proline").intValue(), 0);
163     assertEquals(colCons.get("charged").intValue(), -1);
164     assertEquals(colCons.get("negative").intValue(), 0);
165     assertEquals(colCons.get("polar").intValue(), -1);
166     assertEquals(colCons.get("positive").intValue(), -1);
167     assertEquals(colCons.get("aromatic").intValue(), -1);
168
169     /*
170      * column 4: all gaps - counted as having all properties
171      */
172     colCons = cons.total[4];
173     assertEquals(colCons.get("hydrophobic").intValue(), 1);
174     assertEquals(colCons.get("aliphatic").intValue(), 1);
175     assertEquals(colCons.get("small").intValue(), 1);
176     assertEquals(colCons.get("tiny").intValue(), 1);
177     assertEquals(colCons.get("proline").intValue(), 1);
178     assertEquals(colCons.get("charged").intValue(), 1);
179     assertEquals(colCons.get("negative").intValue(), 1);
180     assertEquals(colCons.get("polar").intValue(), 1);
181     assertEquals(colCons.get("positive").intValue(), 1);
182     assertEquals(colCons.get("aromatic").intValue(), 1);
183
184     /*
185      * column 5: N (small polar) and L (aliphatic hydrophobic) 
186      * have nothing in common!
187      */
188     colCons = cons.total[5];
189     assertEquals(colCons.get("hydrophobic").intValue(), -1);
190     assertEquals(colCons.get("aliphatic").intValue(), -1);
191     assertEquals(colCons.get("small").intValue(), -1);
192     assertEquals(colCons.get("tiny").intValue(), 0);
193     assertEquals(colCons.get("proline").intValue(), 0);
194     assertEquals(colCons.get("charged").intValue(), 0);
195     assertEquals(colCons.get("negative").intValue(), 0);
196     assertEquals(colCons.get("polar").intValue(), -1);
197     assertEquals(colCons.get("positive").intValue(), 0);
198     assertEquals(colCons.get("aromatic").intValue(), 0);
199   }
200
201   /**
202    * Test for the case whether the number of non-gapped sequences in a column
203    * has to be above a threshold
204    */
205   @Test(groups = "Functional")
206   public void testCalculate_threshold()
207   {
208     List<SequenceI> seqs = new ArrayList<SequenceI>();
209     seqs.add(new Sequence("seq1", "VGIV-"));
210     seqs.add(new Sequence("seq2", "V-iL-")); // not case sensitive
211     seqs.add(new Sequence("seq3", "V-IW-"));
212     seqs.add(new Sequence("seq4", "VGLH-"));
213     seqs.add(new Sequence("seq5", "VGLH-"));
214
215     /*
216      * threshold 50% means a residue has to occur 3 or more times
217      * in a column to be counted for conservation
218      */
219     // TODO: ConservationThread uses a value of 3
220     // calculateConservation states it is the minimum number of sequences
221     // but it is treated as percentage threshold in calculate() ?
222     Conservation cons = new Conservation("", 50, seqs, 0, 4);
223     cons.calculate();
224
225     /*
226      * column 0: all V (hydrophobic/aliphatic/small)
227      */
228     Map<String, Integer> colCons = cons.total[0];
229     assertEquals(colCons.get("hydrophobic").intValue(), 1);
230     assertEquals(colCons.get("aliphatic").intValue(), 1);
231     assertEquals(colCons.get("small").intValue(), 1);
232     assertEquals(colCons.get("tiny").intValue(), 0);
233     assertEquals(colCons.get("proline").intValue(), 0);
234     assertEquals(colCons.get("charged").intValue(), 0);
235     assertEquals(colCons.get("negative").intValue(), 0);
236     assertEquals(colCons.get("polar").intValue(), 0);
237     assertEquals(colCons.get("positive").intValue(), 0);
238     assertEquals(colCons.get("aromatic").intValue(), 0);
239
240     /*
241      * column 1: all G (hydrophobic/small/tiny)
242      * gaps are ignored as not above threshold
243      */
244     colCons = cons.total[1];
245     assertEquals(colCons.get("hydrophobic").intValue(), 1);
246     assertEquals(colCons.get("aliphatic").intValue(), 0);
247     assertEquals(colCons.get("small").intValue(), 1);
248     assertEquals(colCons.get("tiny").intValue(), 1);
249     assertEquals(colCons.get("proline").intValue(), 0);
250     assertEquals(colCons.get("charged").intValue(), 0);
251     assertEquals(colCons.get("negative").intValue(), 0);
252     assertEquals(colCons.get("polar").intValue(), 0);
253     assertEquals(colCons.get("positive").intValue(), 0);
254     assertEquals(colCons.get("aromatic").intValue(), 0);
255
256     /*
257      * column 2: I/L (aliphatic/hydrophobic), all others negatively conserved
258      */
259     colCons = cons.total[2];
260     assertEquals(colCons.get("hydrophobic").intValue(), 1);
261     assertEquals(colCons.get("aliphatic").intValue(), 1);
262     assertEquals(colCons.get("small").intValue(), 0);
263     assertEquals(colCons.get("tiny").intValue(), 0);
264     assertEquals(colCons.get("proline").intValue(), 0);
265     assertEquals(colCons.get("charged").intValue(), 0);
266     assertEquals(colCons.get("negative").intValue(), 0);
267     assertEquals(colCons.get("polar").intValue(), 0);
268     assertEquals(colCons.get("positive").intValue(), 0);
269     assertEquals(colCons.get("aromatic").intValue(), 0);
270
271     /*
272      * column 3: nothing above threshold
273      */
274     colCons = cons.total[3];
275     assertTrue(colCons.isEmpty());
276
277     /*
278      * column 4: all gaps - counted as having all properties
279      */
280     colCons = cons.total[4];
281     assertEquals(colCons.get("hydrophobic").intValue(), 1);
282     assertEquals(colCons.get("aliphatic").intValue(), 1);
283     assertEquals(colCons.get("small").intValue(), 1);
284     assertEquals(colCons.get("tiny").intValue(), 1);
285     assertEquals(colCons.get("proline").intValue(), 1);
286     assertEquals(colCons.get("charged").intValue(), 1);
287     assertEquals(colCons.get("negative").intValue(), 1);
288     assertEquals(colCons.get("polar").intValue(), 1);
289     assertEquals(colCons.get("positive").intValue(), 1);
290     assertEquals(colCons.get("aromatic").intValue(), 1);
291   }
292
293   /**
294    * Test the method that derives the conservation 'sequence' and the mouseover
295    * tooltips from the computed conservation
296    */
297   @Test(groups = "Functional")
298   public void testVerdict()
299   {
300     List<SequenceI> seqs = new ArrayList<SequenceI>();
301     seqs.add(new Sequence("seq1", "VGIVV-H"));
302     seqs.add(new Sequence("seq2", "VGILL-H"));
303     seqs.add(new Sequence("seq3", "VGIW--R"));
304     seqs.add(new Sequence("seq4", "VGLHH--"));
305     seqs.add(new Sequence("seq5", "VGLHH-R"));
306     seqs.add(new Sequence("seq6", "VGLHH--"));
307     seqs.add(new Sequence("seq7", "VGLHH-R"));
308     seqs.add(new Sequence("seq8", "VGLHH-R"));
309
310     // calculate with no threshold
311     Conservation cons = new Conservation("", 0, seqs, 0, 6);
312     cons.calculate();
313     // positive and negative conservation where <25% gaps in columns
314     cons.verdict(false, 25);
315
316     /*
317      * verify conservation 'sequence'
318      * cols 0 fully conserved and above threshold (*)
319      * col 2 properties fully conserved (+)
320      * col 3 VLWH 1 positively and 3 negatively conserved properties
321      * col 4 has 1 positively conserved property, but because gap contributes a
322      * 'positive' for all properties, no negative conservation is counted
323      * col 5 is all gaps
324      * col 6 has 25% gaps so fails threshold test
325      */
326     assertEquals(cons.getConsSequence().getSequenceAsString(), "**+41--");
327
328     /*
329      * verify tooltips; conserved properties are sorted alphabetically within
330      * positive followed by negative
331      */
332     assertEquals(cons.getTooltip(0),
333             "aliphatic hydrophobic small !aromatic !charged !negative !polar !positive !proline !tiny");
334     assertEquals(cons.getTooltip(1),
335             "hydrophobic small tiny !aliphatic !aromatic !charged !negative !polar !positive !proline");
336     assertEquals(cons.getTooltip(2),
337             "aliphatic hydrophobic !aromatic !charged !negative !polar !positive !proline !small !tiny");
338     assertEquals(cons.getTooltip(3),
339             "hydrophobic !negative !proline !tiny");
340     assertEquals(cons.getTooltip(4), "hydrophobic");
341     assertEquals(cons.getTooltip(5), "");
342     assertEquals(cons.getTooltip(6), "");
343   }
344 }