271162bcfab92e3685119b9f291baac57660887c
[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.io.AppletFormatAdapter;
28
29 import org.testng.annotations.Test;
30
31 public class AlignmentAnnotationTests
32 {
33   @Test(groups = { "Functional" })
34   public void testCopyConstructor()
35   {
36     SequenceI sq = new Sequence("Foo", "ARAARARARAWEAWEAWRAWEAWE");
37     createAnnotation(sq);
38     AlignmentAnnotation alc, alo = sq.getAnnotation()[0];
39     alc = new AlignmentAnnotation(alo);
40     for (String key : alo.getProperties())
41     {
42       assertEquals("Property mismatch", alo.getProperty(key),
43               alc.getProperty(key));
44     }
45   }
46
47   /**
48    * create some dummy annotation derived from the sequence
49    * 
50    * @param sq
51    */
52   public static void createAnnotation(SequenceI sq)
53   {
54     Annotation[] al = new Annotation[sq.getLength()];
55     for (int i = 0; i < al.length; i++)
56     {
57       al[i] = new Annotation(new Annotation("" + sq.getCharAt(i), "",
58               (char) 0, sq.findPosition(i)));
59     }
60     AlignmentAnnotation alan = new AlignmentAnnotation("For "
61             + sq.getName(), "Fake alignment annot", al);
62     // create a sequence mapping for the annotation vector in its current state
63     alan.createSequenceMapping(sq, sq.getStart(), false);
64     alan.setProperty("CreatedBy", "createAnnotation");
65     sq.addAlignmentAnnotation(alan);
66   }
67
68   /**
69    * use this to test annotation derived from method above as it is transferred
70    * across different sequences derived from same dataset coordinate frame
71    * 
72    * @param ala
73    */
74   public static void testAnnotTransfer(AlignmentAnnotation ala)
75   {
76     assertEquals(
77             "Failed - need annotation created by createAnnotation method",
78             ala.description, "Fake alignment annot");
79     ala.adjustForAlignment();
80     for (int p = 0; p < ala.annotations.length; p++)
81     {
82       if (ala.annotations[p] != null)
83       {
84         assertEquals("Mismatch at position " + p
85                 + " between annotation position value and sequence"
86                 + ala.annotations[p], (int) ala.annotations[p].value,
87                 ala.sequenceRef.findPosition(p));
88       }
89     }
90   }
91
92   /**
93    * Tests the liftOver method and also exercises the functions for remapping
94    * annotation across different reference sequences. Here, the test is between
95    * different dataset frames (annotation transferred by mapping between
96    * sequences)
97    */
98   @Test(groups = { "Functional" })
99   public void testLiftOver()
100   {
101     SequenceI sqFrom = new Sequence("fromLong", "QQQCDEWGH");
102     sqFrom.setStart(10);
103     sqFrom.setEnd(sqFrom.findPosition(sqFrom.getLength() - 1));
104     SequenceI sqTo = new Sequence("toShort", "RCDEW");
105     sqTo.setStart(20);
106     sqTo.setEnd(sqTo.findPosition(sqTo.getLength() - 1));
107     createAnnotation(sqTo);
108     AlignmentAnnotation origTo = sqTo.getAnnotation()[0];
109     createAnnotation(sqFrom);
110     AlignmentAnnotation origFrom = sqFrom.getAnnotation()[0];
111     AlignSeq align = AlignSeq.doGlobalNWAlignment(sqFrom, sqTo,
112             AlignSeq.PEP);
113     SequenceI alSeq1 = new Sequence(sqFrom.getName(), align.getAStr1());
114     alSeq1.setStart(sqFrom.getStart() + align.getSeq1Start() - 1);
115     alSeq1.setEnd(sqFrom.getStart() + align.getSeq1End() - 1);
116     alSeq1.setDatasetSequence(sqFrom);
117     SequenceI alSeq2 = new Sequence(sqTo.getName(), align.getAStr2());
118     alSeq2.setStart(sqTo.getStart() + align.getSeq2Start() - 1);
119     alSeq2.setEnd(sqTo.getStart() + align.getSeq2End() - 1);
120     alSeq2.setDatasetSequence(sqTo);
121     System.out.println(new AppletFormatAdapter()
122             .formatSequences("STH", new Alignment(new SequenceI[] { sqFrom,
123                 alSeq1, sqTo, alSeq2 }), true));
124
125     Mapping mp = align.getMappingFromS1(false);
126
127     AlignmentAnnotation almap1 = new AlignmentAnnotation(
128             sqTo.getAnnotation()[0]);
129     almap1.liftOver(sqFrom, mp);
130     assertEquals(almap1.sequenceRef, sqFrom);
131     alSeq1.addAlignmentAnnotation(almap1);
132     almap1.setSequenceRef(alSeq1);
133     almap1.adjustForAlignment();
134     AlignmentAnnotation almap2 = new AlignmentAnnotation(
135             sqFrom.getAnnotation()[0]);
136     almap2.liftOver(sqTo, mp);
137     assertEquals(almap2.sequenceRef, sqTo);
138
139     alSeq2.addAlignmentAnnotation(almap2);
140     almap2.setSequenceRef(alSeq2);
141     almap2.adjustForAlignment();
142
143     AlignmentI all = new Alignment(new SequenceI[] { alSeq1, alSeq2 });
144     all.addAnnotation(almap1);
145     all.addAnnotation(almap2);
146     System.out.println(new AppletFormatAdapter().formatSequences("STH",
147             all, true));
148
149     for (int p = 0; p < alSeq1.getLength(); p++)
150     {
151       Annotation orig1, trans1, orig2, trans2;
152       trans2 = almap2.annotations[p];
153       orig2 = origFrom.annotations[alSeq1.findPosition(p)
154               - sqFrom.getStart()];
155       orig1 = origTo.annotations[alSeq2.findPosition(p) - sqTo.getStart()];
156       trans1 = almap1.annotations[p];
157       if (trans1 == trans2)
158       {
159         System.out.println("Pos " + p + " mismatch");
160         continue;
161       }
162       assertEquals(
163               "Mismatch on Original From and transferred annotation on 2",
164               (orig2 != null) ? orig2.toString() : null,
165               (trans2 != null) ? trans2.toString() : null);
166       assertEquals(
167               "Mismatch on Original To and transferred annotation on 1",
168               (orig1 != null) ? orig1.toString() : null,
169               (trans1 != null) ? trans1.toString() : null);
170       String alm1 = ""
171               + (almap1.annotations.length > p ? almap1.annotations[p].displayCharacter
172                       : "Out of range");
173       String alm2 = ""
174               + (almap2.annotations.length > p ? almap2.annotations[p].displayCharacter
175                       : "Out of range");
176       assertEquals("Position " + p + " " + alm1 + " " + alm2, alm1, alm2);
177     }
178   }
179
180   @Test(groups = { "Functional" })
181   public void testAdjustForAlignment()
182   {
183     SequenceI seq = new Sequence("TestSeq", "ABCDEFG");
184     seq.createDatasetSequence();
185
186     /*
187      * Annotate positions 3/4/5 (CDE) with values 1/2/3
188      */
189     Annotation[] anns = new Annotation[] { null, null, new Annotation(1),
190         new Annotation(2), new Annotation(3) };
191     AlignmentAnnotation ann = new AlignmentAnnotation("SS",
192             "secondary structure", anns);
193     seq.addAlignmentAnnotation(ann);
194
195     /*
196      * Check annotation map before modifying aligned sequence
197      */
198     assertNull(ann.getAnnotationForPosition(1));
199     assertNull(ann.getAnnotationForPosition(2));
200     assertNull(ann.getAnnotationForPosition(6));
201     assertNull(ann.getAnnotationForPosition(7));
202     assertEquals(1, ann.getAnnotationForPosition(3).value, 0.001d);
203     assertEquals(2, ann.getAnnotationForPosition(4).value, 0.001d);
204     assertEquals(3, ann.getAnnotationForPosition(5).value, 0.001d);
205
206     /*
207      * Trim the displayed sequence to BCD and adjust annotations
208      */
209     seq.setSequence("BCD");
210     seq.setStart(2);
211     seq.setEnd(4);
212     ann.adjustForAlignment();
213
214     /*
215      * Should now have annotations for aligned positions 2, 3Q (CD) only
216      */
217     assertEquals(3, ann.annotations.length);
218     assertNull(ann.annotations[0]);
219     assertEquals(1, ann.annotations[1].value, 0.001);
220     assertEquals(2, ann.annotations[2].value, 0.001);
221   }
222 }