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