6a2a479244c4c9d52ea709fb2dedc34796a69cea
[jalview.git] / src / jalview / schemes / ResidueColourScheme.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.AlignmentI;
24 import jalview.datamodel.AnnotatedCollectionI;
25 import jalview.datamodel.SequenceCollectionI;
26 import jalview.datamodel.SequenceI;
27
28 import java.awt.Color;
29 import java.util.Map;
30
31 /**
32  * Base class for residue-based colour schemes
33  */
34 public abstract class ResidueColourScheme implements ColourSchemeI
35 {
36   public static final String NONE = "None";
37
38   public static final String USER_DEFINED = "User Defined";
39
40   /*
41    * lookup up by character value e.g. 'G' to the colors array index
42    * e.g. if symbolIndex['K'] = 11 then colors[11] is the colour for K
43    */
44   final int[] symbolIndex;
45
46   /*
47    * colour for residue characters as indexed by symbolIndex
48    */
49   Color[] colors = null;
50
51   /* Set when threshold colouring to either pid_gaps or pid_nogaps */
52   protected boolean ignoreGaps = false;
53
54   /**
55    * Creates a new ResidueColourScheme object.
56    * 
57    * @param final int[] index table into colors (ResidueProperties.naIndex or
58    *        ResidueProperties.aaIndex)
59    * @param colors
60    *          colours for symbols in sequences
61    */
62   public ResidueColourScheme(int[] aaOrnaIndex, Color[] colours)
63   {
64     symbolIndex = aaOrnaIndex;
65     this.colors = colours;
66   }
67
68   /**
69    * Creates a new ResidueColourScheme object with a lookup table for indexing
70    * the colour map
71    */
72   public ResidueColourScheme(int[] aaOrNaIndex)
73   {
74     symbolIndex = aaOrNaIndex;
75   }
76
77   /**
78    * Creates a new ResidueColourScheme object - default constructor for
79    * non-sequence dependent colourschemes
80    */
81   public ResidueColourScheme()
82   {
83     symbolIndex = null;
84   }
85
86   /**
87    * Returns the colour for symbol 'A'. Intended for use in a 'fixed colour'
88    * colour scheme (for example a feature colour).
89    */
90   @Override
91   public Color findColour()
92   {
93     // TODO delete this method in favour of ColorUtils.parseColourString()?
94     return findColour('A');
95   }
96
97   /**
98    * Find a colour without an index in a sequence
99    */
100   @Override
101   public Color findColour(char c)
102   {
103     return colors == null ? Color.white : colors[symbolIndex[c]];
104   }
105
106   /**
107    * Default is to call the overloaded method that ignores consensus. A colour
108    * scheme that depends on consensus (for example, Blosum62), should override
109    * this method instead.
110    */
111   @Override
112   public Color findColour(char c, int j, SequenceI seq,
113           String consensusResidue, float pid)
114   {
115     return findColour(c, j, seq);
116   }
117
118   protected Color findColour(char c, int j, SequenceI seq)
119   {
120     Color colour = Color.white;
121
122     if (colors != null && symbolIndex != null && c < symbolIndex.length
123             && symbolIndex[c] < colors.length)
124     {
125       colour = colors[symbolIndex[c]];
126     }
127     // colour = adjustColour(c, j, colour);
128
129     return colour;
130   }
131
132   @Override
133   public void alignmentChanged(AnnotatedCollectionI alignment,
134           Map<SequenceI, SequenceCollectionI> hiddenReps)
135   {
136   }
137
138   /**
139    * Answers false if the colour scheme is nucleotide or peptide specific, and
140    * the data does not match, else true. Override to modify or extend this test
141    * as required.
142    */
143   @Override
144   public boolean isApplicableTo(AnnotatedCollectionI ac)
145   {
146     if (!isPeptideSpecific() && !isNucleotideSpecific())
147     {
148       return true;
149     }
150
151     /*
152      * inspect the data context (alignment) for residue type
153      */
154     boolean nucleotide = false;
155     if (ac instanceof AlignmentI)
156     {
157       nucleotide = ((AlignmentI) ac).isNucleotide();
158     }
159     else
160     {
161       AnnotatedCollectionI context = ac.getContext();
162       if (context instanceof AlignmentI)
163       {
164         nucleotide = ((AlignmentI) context).isNucleotide();
165       }
166       else
167       {
168         // not sure what's going on, play safe
169         return true;
170       }
171     }
172
173     /*
174      * does data type match colour scheme type?
175      */
176     return (nucleotide && isNucleotideSpecific())
177             || (!nucleotide && isPeptideSpecific());
178   }
179
180   /**
181    * Answers true if the colour scheme is normally only for peptide data
182    * 
183    * @return
184    */
185   public boolean isPeptideSpecific()
186   {
187     return false;
188   }
189
190   /**
191    * Answers true if the colour scheme is normally only for nucleotide data
192    * 
193    * @return
194    */
195   public boolean isNucleotideSpecific()
196   {
197     return false;
198   }
199
200   /**
201    * Default method returns true. Override this to return false in colour
202    * schemes that are not determined solely by the sequence symbol.
203    */
204   @Override
205   public boolean isSimple()
206   {
207     return true;
208   }
209 }