JAL-2326 added setup method for JvOptionPane in all Jalveiw test classes to enable...
[jalview.git] / test / jalview / datamodel / AlignmentAnnotationTests.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.datamodel;
22
23 import static org.testng.AssertJUnit.assertEquals;
24 import static org.testng.AssertJUnit.assertNull;
25
26 import jalview.analysis.AlignSeq;
27 import jalview.gui.JvOptionPane;
28 import jalview.io.AppletFormatAdapter;
29
30 import org.testng.annotations.BeforeClass;
31 import org.testng.annotations.Test;
32
33 public class AlignmentAnnotationTests
34 {
35
36   @BeforeClass(alwaysRun = true)
37   public void setUpJvOptionPane()
38   {
39     JvOptionPane.setInteractiveMode(false);
40     JvOptionPane.setMockResponse(JvOptionPane.CANCEL_OPTION);
41   }
42
43   @Test(groups = { "Functional" })
44   public void testCopyConstructor()
45   {
46     SequenceI sq = new Sequence("Foo", "ARAARARARAWEAWEAWRAWEAWE");
47     createAnnotation(sq);
48     AlignmentAnnotation alc, alo = sq.getAnnotation()[0];
49     alc = new AlignmentAnnotation(alo);
50     for (String key : alo.getProperties())
51     {
52       assertEquals("Property mismatch", alo.getProperty(key),
53               alc.getProperty(key));
54     }
55   }
56
57   /**
58    * create some dummy annotation derived from the sequence
59    * 
60    * @param sq
61    */
62   public static void createAnnotation(SequenceI sq)
63   {
64     Annotation[] al = new Annotation[sq.getLength()];
65     for (int i = 0; i < al.length; i++)
66     {
67       al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "",
68               (char) 0, sq.findPosition(i)));
69     }
70     AlignmentAnnotation alan = new AlignmentAnnotation("For "
71             + sq.getName(), "Fake alignment annot", al);
72     // create a sequence mapping for the annotation vector in its current state
73     alan.createSequenceMapping(sq, sq.getStart(), false);
74     alan.setProperty("CreatedBy", "createAnnotation");
75     sq.addAlignmentAnnotation(alan);
76   }
77
78   /**
79    * use this to test annotation derived from method above as it is transferred
80    * across different sequences derived from same dataset coordinate frame
81    * 
82    * @param ala
83    */
84   public static void testAnnotTransfer(AlignmentAnnotation ala)
85   {
86     assertEquals(
87             "Failed - need annotation created by createAnnotation method",
88             ala.description, "Fake alignment annot");
89     ala.adjustForAlignment();
90     for (int p = 0; p < ala.annotations.length; p++)
91     {
92       if (ala.annotations[p] != null)
93       {
94         assertEquals("Mismatch at position " + p
95                 + " between annotation position value and sequence"
96                 + ala.annotations[p], (int) ala.annotations[p].value,
97                 ala.sequenceRef.findPosition(p));
98       }
99     }
100   }
101
102   /**
103    * Tests the liftOver method and also exercises the functions for remapping
104    * annotation across different reference sequences. Here, the test is between
105    * different dataset frames (annotation transferred by mapping between
106    * sequences)
107    */
108   @Test(groups = { "Functional" })
109   public void testLiftOver()
110   {
111     SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
112     sqFrom.setStart(10);
113     sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
114     SequenceI sqTo = new Sequence("toShort", "RCDEW");
115     sqTo.setStart(20);
116     sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
117     createAnnotation(sqTo);
118     AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
119     createAnnotation(sqFrom);
120     AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
121     AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
122             AlignSeq.PEP);
123     SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
124     alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
125     alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
126     alSeq1.setDatasetSequence(sqFrom);
127     SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
128     alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
129     alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
130     alSeq2.setDatasetSequence(sqTo);
131     System.out.println(new AppletFormatAdapter()
132             .formatSequences("STH", new Alignment(new SequenceI[] { sqFrom,
133                 alSeq1, sqTo, alSeq2 }), true));
134
135     Mapping mp = align.getMappingFromS1(false);
136
137     AlignmentAnnotation almap1 = new AlignmentAnnotation(
138             sqTo.getAnnotation()[0]);
139     almap1.liftOver(sqFrom, mp);
140     assertEquals(almap1.sequenceRef, sqFrom);
141     alSeq1.addAlignmentAnnotation(almap1);
142     almap1.setSequenceRef(alSeq1);
143     almap1.adjustForAlignment();
144     AlignmentAnnotation almap2 = new AlignmentAnnotation(
145             sqFrom.getAnnotation()[0]);
146     almap2.liftOver(sqTo, mp);
147     assertEquals(almap2.sequenceRef, sqTo);
148
149     alSeq2.addAlignmentAnnotation(almap2);
150     almap2.setSequenceRef(alSeq2);
151     almap2.adjustForAlignment();
152
153     AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
154     all.addAnnotation(almap1);
155     all.addAnnotation(almap2);
156     System.out.println(new AppletFormatAdapter().formatSequences("STH",
157             all, true));
158
159     for (int p = 0; p < alSeq1.getLength(); p++)
160     {
161       Annotation orig1, trans1, orig2, trans2;
162       trans2 = almap2.annotations[p];
163       orig2 = origFrom.annotations[alSeq1.findPosition(p)
164               - sqFrom.getStart()];
165       orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()];
166       trans1 = almap1.annotations[p];
167       if (trans1 == trans2)
168       {
169         System.out.println("Pos " + p + " mismatch");
170         continue;
171       }
172       assertEquals(
173               "Mismatch on Original From and transferred annotation on 2",
174               (orig2 != null) ? orig2.toString() : null,
175               (trans2 != null) ? trans2.toString() : null);
176       assertEquals(
177               "Mismatch on Original To and transferred annotation on 1",
178               (orig1 != null) ? orig1.toString() : null,
179               (trans1 != null) ? trans1.toString() : null);
180       String alm1 = ""
181               + (almap1.annotations.length > p ? almap1.annotations[p].displayCharacter
182                       : "Out of range");
183       String alm2 = ""
184               + (almap2.annotations.length > p ? almap2.annotations[p].displayCharacter
185                       : "Out of range");
186       assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2);
187     }
188   }
189
190   @Test(groups = { "Functional" })
191   public void testAdjustForAlignment()
192   {
193     SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
194     seq.createDatasetSequence();
195
196     /*
197      * Annotate positions 3/4/5 (CDE) with values 1/2/3
198      */
199     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
200         new Annotation(2), new Annotation(3) };
201     AlignmentAnnotation ann = new AlignmentAnnotation("SS",
202             "secondary structure", anns);
203     seq.addAlignmentAnnotation(ann);
204
205     /*
206      * Check annotation map before modifying aligned sequence
207      */
208     assertNull(ann.getAnnotationForPosition(1));
209     assertNull(ann.getAnnotationForPosition(2));
210     assertNull(ann.getAnnotationForPosition(6));
211     assertNull(ann.getAnnotationForPosition(7));
212     assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d);
213     assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d);
214     assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d);
215
216     /*
217      * Trim the displayed sequence to BCD and adjust annotations
218      */
219     seq.setSequence("BCD");
220     seq.setStart(2);
221     seq.setEnd(4);
222     ann.adjustForAlignment();
223
224     /*
225      * Should now have annotations for aligned positions 2, 3Q (CD) only
226      */
227     assertEquals(3, ann.annotations.length);
228     assertNull(ann.annotations[0]);
229     assertEquals(1, ann.annotations[1].value, 0.001);
230     assertEquals(2, ann.annotations[2].value, 0.001);
231   }
232
233   /**
234    * Test the method that defaults rna symbol to the one matching the preceding
235    * unmatched opening bracket (if any)
236    */
237   @Test(groups = { "Functional" })
238   public void testGetDefaultRnaHelixSymbol()
239   {
240     AlignmentAnnotation ann = new AlignmentAnnotation("SS",
241             "secondary structure", null);
242     assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
243
244     Annotation[] anns = new Annotation[20];
245     ann.annotations = anns;
246     assertEquals("(", ann.getDefaultRnaHelixSymbol(4));
247
248     anns[1] = new Annotation("(", "S", '(', 0f);
249     assertEquals("(", ann.getDefaultRnaHelixSymbol(0));
250     assertEquals("(", ann.getDefaultRnaHelixSymbol(1));
251     assertEquals(")", ann.getDefaultRnaHelixSymbol(2));
252     assertEquals(")", ann.getDefaultRnaHelixSymbol(3));
253
254     /*
255      * .(.[.{.<.}.>.).].
256      */
257     anns[1] = new Annotation("(", "S", '(', 0f);
258     anns[3] = new Annotation("[", "S", '[', 0f);
259     anns[5] = new Annotation("{", "S", '{', 0f);
260     anns[7] = new Annotation("<", "S", '<', 0f);
261     anns[9] = new Annotation("}", "S", '}', 0f);
262     anns[11] = new Annotation(">", "S", '>', 0f);
263     anns[13] = new Annotation(")", "S", ')', 0f);
264     anns[15] = new Annotation("]", "S", ']', 0f);
265
266     String expected = "(())]]}}>>>>]]]](";
267     for (int i = 0; i < expected.length(); i++)
268     {
269       assertEquals("column " + i, String.valueOf(expected.charAt(i)),
270               ann.getDefaultRnaHelixSymbol(i));
271     }
272
273     /*
274      * .(.[.(.).{.}.<.].D.
275      */
276     anns[1] = new Annotation("(", "S", '(', 0f);
277     anns[3] = new Annotation("[", "S", '[', 0f);
278     anns[5] = new Annotation("(", "S", '(', 0f);
279     anns[7] = new Annotation(")", "S", ')', 0f);
280     anns[9] = new Annotation("{", "S", '{', 0f);
281     anns[11] = new Annotation("}", "S", '}', 0f);
282     anns[13] = new Annotation("<", "S", '>', 0f);
283     anns[15] = new Annotation("]", "S", ']', 0f);
284     anns[17] = new Annotation("D", "S", 'D', 0f);
285
286     expected = "(())]]))]]}}]]>>>>dd";
287     for (int i = 0; i < expected.length(); i++)
288     {
289       assertEquals("column " + i, String.valueOf(expected.charAt(i)),
290               ann.getDefaultRnaHelixSymbol(i));
291     }
292   }
293 }