Clover icon

jalviewX

  1. Project Clover database Wed Oct 31 2018 15:13:58 GMT
  2. Package jalview.renderer

File ResidueShader.java

 

Coverage histogram

../../img/srcFileCovDistChart10.png
0% of files have more coverage

Code metrics

34
62
19
1
418
194
42
0.68
3.26
19
2.21

Classes

Class Line # Actions
ResidueShader 50 62 42 7
0.939130493.9%
 

Contributing tests

This file is covered by 148 tests. .

Source view

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.renderer;
22   
23    import jalview.analysis.Conservation;
24    import jalview.api.ViewStyleI;
25    import jalview.datamodel.AnnotatedCollectionI;
26    import jalview.datamodel.ProfileI;
27    import jalview.datamodel.ProfilesI;
28    import jalview.datamodel.SequenceCollectionI;
29    import jalview.datamodel.SequenceI;
30    import jalview.schemes.ColourSchemeI;
31    import jalview.util.ColorUtils;
32    import jalview.util.Comparison;
33   
34    import java.awt.Color;
35    import java.util.Map;
36   
37    /**
38    * A class that computes the colouring of an alignment (or subgroup). Currently
39    * the factors that may influence residue colouring are
40    * <ul>
41    * <li>the colour scheme that provides a colour for each aligned residue</li>
42    * <li>any threshold for colour, based on percentage identity with
43    * consensus</li>
44    * <li>any graduation based on conservation of physico-chemical properties</li>
45    * </ul>
46    *
47    * @author gmcarstairs
48    *
49    */
 
50    public class ResidueShader implements ResidueShaderI
51    {
52    private static final int INITIAL_CONSERVATION = 30;
53   
54    /*
55    * the colour scheme that gives the colour of each residue
56    * before applying any conservation or PID shading
57    */
58    private ColourSchemeI colourScheme;
59   
60    /*
61    * the consensus data for each column
62    */
63    private ProfilesI consensus;
64   
65    /*
66    * if true, apply shading of colour by conservation
67    */
68    private boolean conservationColouring;
69   
70    /*
71    * the physico-chemical property conservation scores for columns, with values
72    * 0-9, '+' (all properties conserved), '*' (residue fully conserved) or '-' (gap)
73    * (may be null if colour by conservation is not selected)
74    */
75    private char[] conservation;
76   
77    /*
78    * minimum percentage identity for colour to be applied;
79    * if above zero, residue must match consensus (or joint consensus)
80    * and column have >= pidThreshold identity with the residue
81    */
82    private int pidThreshold;
83   
84    /*
85    * if true, ignore gaps in percentage identity calculation
86    */
87    private boolean ignoreGaps;
88   
89    /*
90    * setting of the By Conservation slider
91    */
92    private int conservationIncrement = INITIAL_CONSERVATION;
93   
 
94  1227 toggle public ResidueShader(ColourSchemeI cs)
95    {
96  1227 colourScheme = cs;
97    }
98   
99    /**
100    * Default constructor
101    */
 
102  1460 toggle public ResidueShader()
103    {
104    }
105   
106    /**
107    * Constructor given view style settings
108    *
109    * @param viewStyle
110    */
 
111  0 toggle public ResidueShader(ViewStyleI viewStyle)
112    {
113    // TODO remove duplicated storing of conservation / pid thresholds?
114  0 this();
115  0 setConservationApplied(viewStyle.isConservationColourSelected());
116    // setThreshold(viewStyle.getThreshold());
117    }
118   
119    /**
120    * Copy constructor
121    */
 
122  42 toggle public ResidueShader(ResidueShader rs)
123    {
124  42 this.colourScheme = rs.colourScheme;
125  42 this.consensus = rs.consensus;
126  42 this.conservation = rs.conservation;
127  42 this.conservationColouring = rs.conservationColouring;
128  42 this.conservationIncrement = rs.conservationIncrement;
129  42 this.ignoreGaps = rs.ignoreGaps;
130  42 this.pidThreshold = rs.pidThreshold;
131    }
132   
133    /**
134    * @see jalview.renderer.ResidueShaderI#setConsensus(jalview.datamodel.ProfilesI)
135    */
 
136  1518 toggle @Override
137    public void setConsensus(ProfilesI cons)
138    {
139  1518 consensus = cons;
140    }
141   
142    /**
143    * @see jalview.renderer.ResidueShaderI#conservationApplied()
144    */
 
145  798 toggle @Override
146    public boolean conservationApplied()
147    {
148  798 return conservationColouring;
149    }
150   
151    /**
152    * @see jalview.renderer.ResidueShaderI#setConservationApplied(boolean)
153    */
 
154  153 toggle @Override
155    public void setConservationApplied(boolean conservationApplied)
156    {
157  153 conservationColouring = conservationApplied;
158    }
159   
160    /**
161    * @see jalview.renderer.ResidueShaderI#setConservation(jalview.analysis.Conservation)
162    */
 
163  29 toggle @Override
164    public void setConservation(Conservation cons)
165    {
166  29 if (cons == null)
167    {
168  4 conservationColouring = false;
169  4 conservation = null;
170    }
171    else
172    {
173  25 conservationColouring = true;
174  25 conservation = cons.getConsSequence().getSequenceAsString()
175    .toCharArray();
176    }
177   
178    }
179   
180    /**
181    * @see jalview.renderer.ResidueShaderI#alignmentChanged(jalview.datamodel.AnnotatedCollectionI,
182    * java.util.Map)
183    */
 
184  1047 toggle @Override
185    public void alignmentChanged(AnnotatedCollectionI alignment,
186    Map<SequenceI, SequenceCollectionI> hiddenReps)
187    {
188  1047 if (colourScheme != null)
189    {
190  343 colourScheme.alignmentChanged(alignment, hiddenReps);
191    }
192    }
193   
194    /**
195    * @see jalview.renderer.ResidueShaderI#setThreshold(int, boolean)
196    */
 
197  172 toggle @Override
198    public void setThreshold(int consensusThreshold, boolean ignoreGaps)
199    {
200  172 pidThreshold = consensusThreshold;
201  172 this.ignoreGaps = ignoreGaps;
202    }
203   
204    /**
205    * @see jalview.renderer.ResidueShaderI#setConservationInc(int)
206    */
 
207  87 toggle @Override
208    public void setConservationInc(int i)
209    {
210  87 conservationIncrement = i;
211    }
212   
213    /**
214    * @see jalview.renderer.ResidueShaderI#getConservationInc()
215    */
 
216  36 toggle @Override
217    public int getConservationInc()
218    {
219  36 return conservationIncrement;
220    }
221   
222    /**
223    * @see jalview.renderer.ResidueShaderI#getThreshold()
224    */
 
225  54 toggle @Override
226    public int getThreshold()
227    {
228  54 return pidThreshold;
229    }
230   
231    /**
232    * @see jalview.renderer.ResidueShaderI#findColour(char, int,
233    * jalview.datamodel.SequenceI)
234    */
 
235  350635 toggle @Override
236    public Color findColour(char symbol, int position, SequenceI seq)
237    {
238  350635 if (colourScheme == null)
239    {
240  0 return Color.white; // Colour is 'None'
241    }
242   
243    /*
244    * get 'base' colour
245    */
246  350635 ProfileI profile = consensus == null ? null : consensus.get(position);
247  350635 String modalResidue = profile == null ? null
248    : profile.getModalResidue();
249  350635 float pid = profile == null ? 0f
250    : profile.getPercentageIdentity(ignoreGaps);
251  350635 Color colour = colourScheme.findColour(symbol, position, seq,
252    modalResidue, pid);
253   
254    /*
255    * apply PID threshold and consensus fading if in force
256    */
257  350635 if (!Comparison.isGap(symbol))
258    {
259  343416 colour = adjustColour(symbol, position, colour);
260    }
261   
262  350635 return colour;
263    }
264   
265    /**
266    * Adjusts colour by applying thresholding or conservation shading, if in
267    * force. That is
268    * <ul>
269    * <li>if there is a threshold set for colouring, and the residue doesn't
270    * match the consensus (or a joint consensus) residue, or the consensus score
271    * is not above the threshold, then the colour is set to white</li>
272    * <li>if conservation colouring is selected, the colour is faded by an amount
273    * depending on the conservation score for the column, and the conservation
274    * colour threshold</li>
275    * </ul>
276    *
277    * @param symbol
278    * @param column
279    * @param colour
280    * @return
281    */
 
282  343416 toggle protected Color adjustColour(char symbol, int column, Color colour)
283    {
284  343416 if (!aboveThreshold(symbol, column))
285    {
286  3191 colour = Color.white;
287    }
288   
289  343416 if (conservationColouring)
290    {
291  10304 colour = applyConservation(colour, column);
292    }
293  343416 return colour;
294    }
295   
296    /**
297    * Answers true if there is a consensus profile for the specified column, and
298    * the given residue matches the consensus (or joint consensus) residue for
299    * the column, and the percentage identity for the profile is equal to or
300    * greater than the current threshold; else answers false. The percentage
301    * calculation depends on whether or not we are ignoring gapped sequences.
302    *
303    * @param residue
304    * @param column
305    * (index into consensus profiles)
306    *
307    * @return
308    * @see #setThreshold(int, boolean)
309    */
 
310  343433 toggle protected boolean aboveThreshold(char residue, int column)
311    {
312  343433 if (pidThreshold == 0)
313    {
314  335511 return true;
315    }
316  7922 if ('a' <= residue && residue <= 'z')
317    {
318    // TO UPPERCASE !!!
319    // Faster than toUpperCase
320  4 residue -= ('a' - 'A');
321    }
322   
323  7922 if (consensus == null)
324    {
325  0 return false;
326    }
327   
328  7922 ProfileI profile = consensus.get(column);
329   
330    /*
331    * test whether this is the consensus (or joint consensus) residue
332    */
333  7922 if (profile != null
334    && profile.getModalResidue().contains(String.valueOf(residue)))
335    {
336  5372 if (profile.getPercentageIdentity(ignoreGaps) >= pidThreshold)
337    {
338  4724 return true;
339    }
340    }
341   
342  3198 return false;
343    }
344   
345    /**
346    * Applies a combination of column conservation score, and conservation
347    * percentage slider, to 'bleach' out the residue colours towards white.
348    * <p>
349    * If a column is fully conserved (identical residues, conservation score 11,
350    * shown as *), or all 10 physico-chemical properties are conserved
351    * (conservation score 10, shown as +), then the colour is left unchanged.
352    * <p>
353    * Otherwise a 'bleaching' factor is computed and applied to the colour. This
354    * is designed to fade colours for scores of 0-9 completely to white at slider
355    * positions ranging from 18% - 100% respectively.
356    *
357    * @param currentColour
358    * @param column
359    *
360    * @return bleached (or unmodified) colour
361    */
 
362  10345 toggle protected Color applyConservation(Color currentColour, int column)
363    {
364  10345 if (conservation == null || conservation.length <= column)
365    {
366  433 return currentColour;
367    }
368  9912 char conservationScore = conservation[column];
369   
370    /*
371    * if residues are fully conserved (* or 11), or all properties
372    * are conserved (+ or 10), leave colour unchanged
373    */
374  9912 if (conservationScore == '*' || conservationScore == '+'
375    || conservationScore == (char) 10
376    || conservationScore == (char) 11)
377    {
378  426 return currentColour;
379    }
380   
381  9486 if (Comparison.isGap(conservationScore))
382    {
383  3024 return Color.white;
384    }
385   
386    /*
387    * convert score 0-9 to a bleaching factor 1.1 - 0.2
388    */
389  6462 float bleachFactor = (11 - (conservationScore - '0')) / 10f;
390   
391    /*
392    * scale this up by 0-5 (percentage slider / 20)
393    * as a result, scores of: 0 1 2 3 4 5 6 7 8 9
394    * fade to white at slider value: 18 20 22 25 29 33 40 50 67 100%
395    */
396  6462 bleachFactor *= (conservationIncrement / 20f);
397   
398  6462 return ColorUtils.bleachColour(currentColour, bleachFactor);
399    }
400   
401    /**
402    * @see jalview.renderer.ResidueShaderI#getColourScheme()
403    */
 
404  353374 toggle @Override
405    public ColourSchemeI getColourScheme()
406    {
407  353374 return this.colourScheme;
408    }
409   
410    /**
411    * @see jalview.renderer.ResidueShaderI#setColourScheme(jalview.schemes.ColourSchemeI)
412    */
 
413  234 toggle @Override
414    public void setColourScheme(ColourSchemeI cs)
415    {
416  234 colourScheme = cs;
417    }
418    }