Merge branch 'develop' into features/JAL-2360colourSchemeApplicability
[jalview.git] / src / jalview / schemes / TCoffeeColourScheme.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.schemes;
22
23 import jalview.datamodel.AlignmentAnnotation;
24 import jalview.datamodel.AlignmentI;
25 import jalview.datamodel.AnnotatedCollectionI;
26 import jalview.datamodel.Annotation;
27 import jalview.datamodel.SequenceCollectionI;
28 import jalview.datamodel.SequenceI;
29 import jalview.io.TCoffeeScoreFile;
30
31 import java.awt.Color;
32 import java.util.ArrayList;
33 import java.util.IdentityHashMap;
34 import java.util.List;
35 import java.util.Map;
36
37 /**
38  * Defines the color score for T-Coffee MSA
39  * <p>
40  * See http://tcoffee.org
41  * 
42  * 
43  * @author Paolo Di Tommaso
44  * 
45  */
46 public class TCoffeeColourScheme extends ResidueColourScheme
47 {
48   IdentityHashMap<SequenceI, Color[]> seqMap;
49
50   /**
51    * Default constructor (required for Class.newInstance())
52    */
53   public TCoffeeColourScheme()
54   {
55
56   }
57
58   /**
59    * the color scheme needs to look at the alignment to get and cache T-COFFEE
60    * scores
61    * 
62    * @param alignment
63    *          - annotated sequences to be searched
64    */
65   public TCoffeeColourScheme(AnnotatedCollectionI alignment)
66   {
67     alignmentChanged(alignment, null);
68   }
69
70   /**
71    * Finds the TCoffeeScore annotation (if any) for each sequence and notes the
72    * annotation colour for each column position. The colours are fixed for
73    * scores 0-9 and are set when annotation is parsed.
74    * 
75    * @see TCoffeeScoreFile#annotateAlignment(AlignmentI, boolean)
76    */
77   @Override
78   public void alignmentChanged(AnnotatedCollectionI alignment,
79           Map<SequenceI, SequenceCollectionI> hiddenReps)
80   {
81     // TODO: if sequences have been represented and they have scores, could
82     // compute an average sequence score for the representative
83
84     // assume only one set of TCOFFEE scores - but could have more than one
85     // potentially.
86     List<AlignmentAnnotation> annots = new ArrayList<AlignmentAnnotation>();
87     // Search alignment to get all tcoffee annotation and pick one set of
88     // annotation to use to colour seqs.
89     seqMap = new IdentityHashMap<SequenceI, Color[]>();
90     AnnotatedCollectionI alcontext = alignment instanceof AlignmentI ? alignment
91             : alignment.getContext();
92     if (alcontext == null)
93     {
94       return;
95     }
96     int w = 0;
97     for (AlignmentAnnotation al : alcontext
98             .findAnnotation(TCoffeeScoreFile.TCOFFEE_SCORE))
99     {
100       if (al.sequenceRef != null && !al.belowAlignment)
101       {
102         annots.add(al);
103         if (w < al.annotations.length)
104         {
105           w = al.annotations.length;
106         }
107         Color[] scores = new Color[al.annotations.length];
108         int i = 0;
109         for (Annotation an : al.annotations)
110         {
111           scores[i++] = (an != null) ? an.colour : Color.white;
112         }
113         seqMap.put(al.sequenceRef, scores);
114       }
115     }
116     // TODO: compute average colour for each symbol type in each column - gives
117     // a second order colourscheme for colouring a sequence logo derived from
118     // the alignment (colour reflects quality of alignment for each residue
119     // class)
120   }
121
122   @Override
123   public Color findColour(char c, int j, SequenceI seq)
124   {
125     if (seqMap == null)
126     {
127       return Color.WHITE;
128     }
129     Color[] cols = seqMap.get(seq);
130     if (cols == null)
131     {
132       // see above TODO about computing a colour for each residue in each
133       // column: cc = _rcols[i][indexFor[c]];
134       return Color.white;
135     }
136
137     if (j < 0 || j >= cols.length)
138     {
139       return Color.white;
140     }
141     return cols[j];
142   }
143
144   @Override
145   public ColourSchemeI getInstance(AnnotatedCollectionI sg,
146           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
147   {
148     return new TCoffeeColourScheme(sg);
149   }
150
151   /**
152    * Answers true if the data has TCoffee score annotation
153    */
154   @Override
155   public boolean isApplicableTo(AnnotatedCollectionI ac)
156   {
157     AnnotatedCollectionI alcontext = ac instanceof AlignmentI ? ac : ac
158             .getContext();
159     if (alcontext == null)
160     {
161       return false;
162     }
163     Iterable<AlignmentAnnotation> anns = alcontext
164             .findAnnotation(TCoffeeScoreFile.TCOFFEE_SCORE);
165     return anns.iterator().hasNext();
166   }
167
168   @Override
169   public String getSchemeName()
170   {
171     return JalviewColourScheme.TCoffee.toString();
172   }
173
174   @Override
175   public boolean isSimple()
176   {
177     return false;
178   }
179 }