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