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