JAL-1492 JAL-1397 JAL-643 JAL-969 factory method to clone and apply colour scheme...
[jalview.git] / src / jalview / schemes / UserColourScheme.java
1 /*
2  * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.0b1)
3  * Copyright (C) 2014 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 of the License, or (at your option) any later version.
10  *  
11  * Jalview is distributed in the hope that it will be useful, but 
12  * WITHOUT ANY WARRANTY; without even the implied warranty 
13  * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
14  * PURPOSE.  See the GNU General Public License for more details.
15  * 
16  * You should have received a copy of the GNU General Public License along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
17  * The Jalview Authors are detailed in the 'AUTHORS' file.
18  */
19 package jalview.schemes;
20
21 import java.awt.Color;
22 import java.util.Map;
23 import java.util.StringTokenizer;
24
25 import jalview.datamodel.AnnotatedCollectionI;
26 import jalview.datamodel.SequenceCollectionI;
27 import jalview.datamodel.SequenceI;
28
29 public class UserColourScheme extends ResidueColourScheme
30 {
31   Color[] lowerCaseColours;
32
33   protected String schemeName;
34
35   public UserColourScheme()
36   {
37     super(ResidueProperties.aaIndex);
38   }
39
40   public UserColourScheme(Color[] newColors)
41   {
42     super(ResidueProperties.aaIndex);
43     colors = newColors;
44   }
45   @Override
46   public ColourSchemeI applyTo(AnnotatedCollectionI sg,
47           Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
48   {
49     UserColourScheme usc = new UserColourScheme(colors);
50     if (lowerCaseColours!=null) {
51       usc.schemeName = new String(schemeName);
52       usc.lowerCaseColours = new Color[lowerCaseColours.length];
53       System.arraycopy(lowerCaseColours, 0, usc.lowerCaseColours, 0, lowerCaseColours.length);
54     }
55     return usc;
56   }
57   public UserColourScheme(String colour)
58   {
59     super(ResidueProperties.aaIndex);
60     Color col = getColourFromString(colour);
61
62     if (col == null)
63     {
64       System.out.println("Unknown colour!! " + colour);
65       col = createColourFromName(colour);
66     }
67
68     colors = new Color[24];
69     for (int i = 0; i < 24; i++)
70     {
71       colors[i] = col;
72     }
73     schemeName = colour;
74   }
75
76   public Color[] getColours()
77   {
78     return colors;
79   }
80
81   public Color[] getLowerCaseColours()
82   {
83     return lowerCaseColours;
84   }
85
86   public void setName(String name)
87   {
88     schemeName = name;
89   }
90
91   public String getName()
92   {
93     return schemeName;
94   }
95
96   public Color getColourFromString(String colour)
97   {
98     colour = colour.trim();
99
100     Color col = null;
101     try
102     {
103       int value = Integer.parseInt(colour, 16);
104       col = new Color(value);
105     } catch (NumberFormatException ex)
106     {
107     }
108
109     if (col == null)
110     {
111       col = ColourSchemeProperty.getAWTColorFromName(colour);
112     }
113
114     if (col == null)
115     {
116       try
117       {
118         java.util.StringTokenizer st = new java.util.StringTokenizer(
119                 colour, ",");
120         int r = Integer.parseInt(st.nextToken());
121         int g = Integer.parseInt(st.nextToken());
122         int b = Integer.parseInt(st.nextToken());
123         col = new Color(r, g, b);
124       } catch (Exception ex)
125       {
126       }
127     }
128
129     return col;
130
131   }
132
133   public Color createColourFromName(String name)
134   {
135     int r, g, b;
136
137     int lsize = name.length();
138     int start = 0, end = lsize / 3;
139
140     int rgbOffset = Math.abs(name.hashCode() % 10) * 15;
141
142     r = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
143     start = end;
144     end += lsize / 3;
145     if (end > lsize)
146     {
147       end = lsize;
148     }
149
150     g = Math.abs(name.substring(start, end).hashCode() + rgbOffset) % 210 + 20;
151
152     b = Math.abs(name.substring(end).hashCode() + rgbOffset) % 210 + 20;
153
154     Color color = new Color(r, g, b);
155
156     return color;
157   }
158
159   public void parseAppletParameter(String paramValue)
160   {
161     StringTokenizer st = new StringTokenizer(paramValue, ";");
162     StringTokenizer st2;
163     String token = null, colour, residues;
164     try
165     {
166       while (st.hasMoreElements())
167       {
168         token = st.nextToken().trim();
169         residues = token.substring(0, token.indexOf("="));
170         colour = token.substring(token.indexOf("=") + 1);
171
172         st2 = new StringTokenizer(residues, " ,");
173         while (st2.hasMoreTokens())
174         {
175           token = st2.nextToken();
176
177           if (ResidueProperties.aaIndex[token.charAt(0)] == -1)
178           {
179             continue;
180           }
181
182           int colIndex = ResidueProperties.aaIndex[token.charAt(0)];
183
184           if (token.equalsIgnoreCase("lowerCase"))
185           {
186             if (lowerCaseColours == null)
187             {
188               lowerCaseColours = new Color[23];
189             }
190             for (int i = 0; i < 23; i++)
191             {
192               if (lowerCaseColours[i] == null)
193               {
194                 lowerCaseColours[i] = getColourFromString(colour);
195               }
196             }
197
198             continue;
199           }
200
201           if (token.equals(token.toLowerCase()))
202           {
203             if (lowerCaseColours == null)
204             {
205               lowerCaseColours = new Color[23];
206             }
207             lowerCaseColours[colIndex] = getColourFromString(colour);
208           }
209           else
210           {
211             colors[colIndex] = getColourFromString(colour);
212           }
213         }
214       }
215     } catch (Exception ex)
216     {
217       System.out.println("Error parsing userDefinedColours:\n" + token
218               + "\n" + ex);
219     }
220
221   }
222
223   @Override
224   public Color findColour(char c, int j, SequenceI seq)
225   {
226     Color currentColour;
227     int index = ResidueProperties.aaIndex[c];
228
229     if ((threshold == 0) || aboveThreshold(c, j))
230     {
231       if (lowerCaseColours != null && 'a' <= c && c <= 'z')
232       {
233         currentColour = lowerCaseColours[index];
234       }
235       else
236       {
237         currentColour = colors[index];
238       }
239     }
240     else
241     {
242       currentColour = Color.white;
243     }
244
245     if (conservationColouring)
246     {
247       currentColour = applyConservation(currentColour, j);
248     }
249
250     return currentColour;
251   }
252
253   public void setLowerCaseColours(Color[] lcolours)
254   {
255     lowerCaseColours = lcolours;
256   }
257
258 }