Merge branch 'features/JAL-2360colourSchemeApplicability' into features/JAL-2371colle...
[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    * Find a colour without an index in a sequence
88    */
89   @Override
90   public Color findColour(char c)
91   {
92     return colors == null ? Color.white : colors[symbolIndex[c]];
93   }
94
95   /**
96    * Default is to call the overloaded method that ignores consensus. A colour
97    * scheme that depends on consensus (for example, Blosum62), should override
98    * this method instead.
99    */
100   @Override
101   public Color findColour(char c, int j, SequenceI seq,
102           String consensusResidue, float pid)
103   {
104     return findColour(c, j, seq);
105   }
106
107   protected Color findColour(char c, int j, SequenceI seq)
108   {
109     Color colour = Color.white;
110
111     if (colors != null && symbolIndex != null && c < symbolIndex.length
112             && symbolIndex[c] < colors.length)
113     {
114       colour = colors[symbolIndex[c]];
115     }
116     // colour = adjustColour(c, j, colour);
117
118     return colour;
119   }
120
121   @Override
122   public void alignmentChanged(AnnotatedCollectionI alignment,
123           Map<SequenceI, SequenceCollectionI> hiddenReps)
124   {
125   }
126
127   /**
128    * Answers false if the colour scheme is nucleotide or peptide specific, and
129    * the data does not match, else true. Override to modify or extend this test
130    * as required.
131    */
132   @Override
133   public boolean isApplicableTo(AnnotatedCollectionI ac)
134   {
135     if (!isPeptideSpecific() && !isNucleotideSpecific())
136     {
137       return true;
138     }
139
140     /*
141      * inspect the data context (alignment) for residue type
142      */
143     boolean nucleotide = false;
144     if (ac instanceof AlignmentI)
145     {
146       nucleotide = ((AlignmentI) ac).isNucleotide();
147     }
148     else
149     {
150       AnnotatedCollectionI context = ac.getContext();
151       if (context instanceof AlignmentI)
152       {
153         nucleotide = ((AlignmentI) context).isNucleotide();
154       }
155       else
156       {
157         // not sure what's going on, play safe
158         return true;
159       }
160     }
161
162     /*
163      * does data type match colour scheme type?
164      */
165     return (nucleotide && isNucleotideSpecific())
166             || (!nucleotide && isPeptideSpecific());
167   }
168
169   /**
170    * Answers true if the colour scheme is normally only for peptide data
171    * 
172    * @return
173    */
174   public boolean isPeptideSpecific()
175   {
176     return false;
177   }
178
179   /**
180    * Answers true if the colour scheme is normally only for nucleotide data
181    * 
182    * @return
183    */
184   public boolean isNucleotideSpecific()
185   {
186     return false;
187   }
188
189   /**
190    * Default method returns true. Override this to return false in colour
191    * schemes that are not determined solely by the sequence symbol.
192    */
193   @Override
194   public boolean isSimple()
195   {
196     return true;
197   }
198 }