package jalview.schemes; import jalview.analysis.Conservation; import jalview.datamodel.AnnotatedCollectionI; import jalview.datamodel.ProfileI; import jalview.datamodel.ProfilesI; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; import jalview.util.ColorUtils; import jalview.util.Comparison; import java.awt.Color; import java.util.Map; /** * A data bean that holds the information to determine the colour scheme of an * alignment (or subgroup), consisting of * * * @author gmcarstairs * */ public class CollectionColourScheme implements CollectionColourSchemeI { private ColourSchemeI colourScheme; private ProfilesI consensus; private boolean conservationColouring; private char[] conservation; private int threshold; private boolean ignoreGaps; private int inc; public CollectionColourScheme(ColourSchemeI cs) { colourScheme = cs; } /** * Default constructor */ public CollectionColourScheme() { } /** * @see jalview.schemes.CollectionColourSchemeI#setConsensus(jalview.datamodel.ProfilesI) */ @Override public void setConsensus(ProfilesI cons) { consensus = cons; } /** * @see jalview.schemes.CollectionColourSchemeI#conservationApplied() */ @Override public boolean conservationApplied() { return conservationColouring; } /** * @see jalview.schemes.CollectionColourSchemeI#setConservationApplied(boolean) */ @Override public void setConservationApplied(boolean conservationApplied) { conservationColouring = conservationApplied; } /** * @see jalview.schemes.CollectionColourSchemeI#setConservation(jalview.analysis.Conservation) */ @Override public void setConservation(Conservation cons) { if (cons == null) { conservationColouring = false; conservation = null; } else { conservationColouring = true; conservation = cons.getConsSequence().getSequenceAsString() .toCharArray(); } } /** * @see jalview.schemes.CollectionColourSchemeI#alignmentChanged(jalview.datamodel.AnnotatedCollectionI, * java.util.Map) */ @Override public void alignmentChanged(AnnotatedCollectionI alignment, Map hiddenReps) { if (colourScheme != null) { colourScheme.alignmentChanged(alignment, hiddenReps); } } /** * @see jalview.schemes.CollectionColourSchemeI#setThreshold(int, boolean) */ @Override public void setThreshold(int consensusThreshold, boolean ignoreGaps) { threshold = consensusThreshold; this.ignoreGaps = ignoreGaps; } /** * @see jalview.schemes.CollectionColourSchemeI#setConservationInc(int) */ @Override public void setConservationInc(int i) { inc = i; } /** * @see jalview.schemes.CollectionColourSchemeI#getConservationInc() */ @Override public int getConservationInc() { return inc; } /** * @see jalview.schemes.CollectionColourSchemeI#getThreshold() */ @Override public int getThreshold() { return threshold; } /** * @see jalview.schemes.CollectionColourSchemeI#findColour(char, int, * jalview.datamodel.SequenceI) */ @Override public Color findColour(char symbol, int position, SequenceI seq) { /* * get 'base' colour */ ProfileI profile = consensus == null ? null : consensus.get(position); String modalResidue = profile == null ? null : profile .getModalResidue(); float pid = profile == null ? 0f : profile .getPercentageIdentity(ignoreGaps); Color colour = colourScheme == null ? Color.white : colourScheme .findColour(symbol, position, seq, modalResidue, pid); /* * apply PID threshold and consensus fading if in force */ colour = adjustColour(symbol, position, colour); return colour; } /** * Adjusts colour by applying thresholding or conservation shading, if in * force. That is * * * @param symbol * @param column * @param colour * @return */ protected Color adjustColour(char symbol, int column, Color colour) { if (!aboveThreshold(symbol, column)) { colour = Color.white; } if (conservationColouring) { colour = applyConservation(colour, column); } return colour; } /** * Answers true if there is a consensus profile for the specified column, and * the given residue matches the consensus (or joint consensus) residue for * the column, and the percentage identity for the profile is equal to or * greater than the current threshold; else answers false. The percentage * calculation depends on whether or not we are ignoring gapped sequences. * * @param residue * @param column * (index into consensus profiles) * * @return * @see #setThreshold(int, boolean) */ protected boolean aboveThreshold(char residue, int column) { if (threshold == 0) { return true; } if ('a' <= residue && residue <= 'z') { // TO UPPERCASE !!! // Faster than toUpperCase residue -= ('a' - 'A'); } if (consensus == null) { return false; } ProfileI profile = consensus.get(column); /* * test whether this is the consensus (or joint consensus) residue */ if (profile != null && profile.getModalResidue().contains(String.valueOf(residue))) { if (profile.getPercentageIdentity(ignoreGaps) >= threshold) { return true; } } return false; } /** * Applies a combination of column conservation score, and conservation * percentage slider, to 'bleach' out the residue colours towards white. *

* If a column is fully conserved (identical residues, conservation score 11, * shown as *), or all 10 physico-chemical properties are conserved * (conservation score 10, shown as +), then the colour is left unchanged. *

* Otherwise a 'bleaching' factor is computed and applied to the colour. This * is designed to fade colours for scores of 0-9 completely to white at slider * positions ranging from 18% - 100% respectively. * * @param currentColour * @param column * * @return bleached (or unmodified) colour */ protected Color applyConservation(Color currentColour, int column) { if (conservation == null || conservation.length <= column) { return currentColour; } char conservationScore = conservation[column]; /* * if residues are fully conserved (* or 11), or all properties * are conserved (+ or 10), leave colour unchanged */ if (conservationScore == '*' || conservationScore == '+' || conservationScore == (char) 10 || conservationScore == (char) 11) { return currentColour; } if (Comparison.isGap(conservationScore)) { return Color.white; } /* * convert score 0-9 to a bleaching factor 1.1 - 0.2 */ float bleachFactor = (11 - (conservationScore - '0')) / 10f; /* * scale this up by 0-5 (percentage slider / 20) * as a result, scores of: 0 1 2 3 4 5 6 7 8 9 * fade to white at slider value: 18 20 22 25 29 33 40 50 67 100% */ bleachFactor *= (inc / 20f); return ColorUtils.bleachColour(currentColour, bleachFactor); } /** * @see jalview.schemes.CollectionColourSchemeI#getColourScheme() */ @Override public ColourSchemeI getColourScheme() { return this.colourScheme; } /** * @see jalview.schemes.CollectionColourSchemeI#setColourScheme(jalview.schemes.ColourSchemeI) */ @Override public void setColourScheme(ColourSchemeI cs) { colourScheme = cs; } }