X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fschemes%2FAnnotationColourGradient.java;h=c74fdbc62f83ce0dd089217dd817b08685d37483;hb=424648b2e57e45eaa21c006b44828d8fca418581;hp=c6daa662a2ea321f69e19d35b754819c4e4928a8;hpb=a8f483d04205bb8273ee311c12968b7e86d205fa;p=jalview.git diff --git a/src/jalview/schemes/AnnotationColourGradient.java b/src/jalview/schemes/AnnotationColourGradient.java index c6daa66..c74fdbc 100755 --- a/src/jalview/schemes/AnnotationColourGradient.java +++ b/src/jalview/schemes/AnnotationColourGradient.java @@ -1,19 +1,21 @@ /* - * Jalview - A Sequence Alignment Editor and Viewer (Version 2.8.2) - * Copyright (C) 2014 The Jalview Authors + * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$) + * Copyright (C) $$Year-Rel$$ The Jalview Authors * * This file is part of Jalview. * * Jalview is free software: you can redistribute it and/or * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * as published by the Free Software Foundation, either version 3 + * of the License, or (at your option) any later version. * * Jalview is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty * of MERCHANTABILITY or FITNESS FOR A PARTICULAR * PURPOSE. See the GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along with Jalview. If not, see . + * You should have received a copy of the GNU General Public License + * along with Jalview. If not, see . * The Jalview Authors are detailed in the 'AUTHORS' file. */ package jalview.schemes; @@ -21,9 +23,12 @@ package jalview.schemes; import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.AlignmentI; import jalview.datamodel.AnnotatedCollectionI; +import jalview.datamodel.Annotation; import jalview.datamodel.GraphLine; import jalview.datamodel.SequenceCollectionI; import jalview.datamodel.SequenceI; +import jalview.renderer.AnnotationRenderer; +import jalview.util.Comparison; import java.awt.Color; import java.util.IdentityHashMap; @@ -37,42 +42,60 @@ public class AnnotationColourGradient extends FollowerColourScheme public static final int ABOVE_THRESHOLD = 1; - public AlignmentAnnotation annotation; + private final AlignmentAnnotation annotation; - int aboveAnnotationThreshold = -1; + private final int aboveAnnotationThreshold; public boolean thresholdIsMinMax = false; - GraphLine annotationThreshold; + private GraphLine annotationThreshold; - float r1, g1, b1, rr, gg, bb, dr, dg, db; + private int redMin; + + private int greenMin; + + private int blueMin; + + private int redRange; + + private int greenRange; + + private int blueRange; private boolean predefinedColours = false; private boolean seqAssociated = false; - IdentityHashMap seqannot = null; + /** + * false if the scheme was constructed without a minColour and maxColour used + * to decide if existing colours should be taken from annotation elements when + * they exist + */ + private boolean noGradient = false; + + private IdentityHashMap seqannot = null; + @Override - public ColourSchemeI applyTo(AnnotatedCollectionI sg, + public ColourSchemeI getInstance(AnnotatedCollectionI sg, Map hiddenRepSequences) { - AnnotationColourGradient acg = new AnnotationColourGradient(annotation, colourScheme, aboveAnnotationThreshold); + AnnotationColourGradient acg = new AnnotationColourGradient(annotation, + getColourScheme(), aboveAnnotationThreshold); acg.thresholdIsMinMax = thresholdIsMinMax; - acg.annotationThreshold = (annotationThreshold==null) ? null : new GraphLine(annotationThreshold); - acg.r1 = r1; - acg.g1 = g1; - acg.b1 = b1; - acg.rr = rr; - acg.gg = gg; - acg.bb = bb; - acg.dr = dr; - acg.dg = dg; - acg.db = db; + acg.annotationThreshold = (annotationThreshold == null) ? null + : new GraphLine(annotationThreshold); + acg.redMin = redMin; + acg.greenMin = greenMin; + acg.blueMin = blueMin; + acg.redRange = redRange; + acg.greenRange = greenRange; + acg.blueRange = blueRange; acg.predefinedColours = predefinedColours; acg.seqAssociated = seqAssociated; - + acg.noGradient = noGradient; return acg; } + /** * Creates a new AnnotationColourGradient object. */ @@ -81,11 +104,12 @@ public class AnnotationColourGradient extends FollowerColourScheme { if (originalColour instanceof AnnotationColourGradient) { - colourScheme = ((AnnotationColourGradient) originalColour).colourScheme; + setColourScheme(((AnnotationColourGradient) originalColour) + .getColourScheme()); } else { - colourScheme = originalColour; + setColourScheme(originalColour); } this.annotation = annotation; @@ -96,6 +120,16 @@ public class AnnotationColourGradient extends FollowerColourScheme { annotationThreshold = annotation.threshold; } + // clear values so we don't get weird black bands... + redMin = 254; + greenMin = 254; + blueMin = 254; + redRange = 0; + greenRange = 0; + blueRange = 0; + + noGradient = true; + checkLimits(); } /** @@ -113,13 +147,28 @@ public class AnnotationColourGradient extends FollowerColourScheme annotationThreshold = annotation.threshold; } - r1 = minColour.getRed(); - g1 = minColour.getGreen(); - b1 = minColour.getBlue(); + redMin = minColour.getRed(); + greenMin = minColour.getGreen(); + blueMin = minColour.getBlue(); - rr = maxColour.getRed() - r1; - gg = maxColour.getGreen() - g1; - bb = maxColour.getBlue() - b1; + redRange = maxColour.getRed() - redMin; + greenRange = maxColour.getGreen() - greenMin; + blueRange = maxColour.getBlue() - blueMin; + + noGradient = false; + checkLimits(); + } + + private void checkLimits() + { + aamax = annotation.graphMax; + aamin = annotation.graphMin; + if (annotation.isRNA()) + { + // reset colour palette + ColourSchemeProperty.resetRnaHelicesShading(); + ColourSchemeProperty.initRnaHelicesShading(1 + (int) aamax); + } } @Override @@ -136,26 +185,48 @@ public class AnnotationColourGradient extends FollowerColourScheme } else { - seqannot = new IdentityHashMap(); + seqannot = new IdentityHashMap<>(); } // resolve the context containing all the annotation for the sequence - AnnotatedCollectionI alcontext = alignment instanceof AlignmentI ? alignment : alignment.getContext(); - for (AlignmentAnnotation alan : alcontext.findAnnotation(annotation - .getCalcId())) + AnnotatedCollectionI alcontext = alignment instanceof AlignmentI + ? alignment + : alignment.getContext(); + boolean f = true, rna = false; + for (AlignmentAnnotation alan : alcontext + .findAnnotation(annotation.getCalcId())) { if (alan.sequenceRef != null - && (alan.label != null && annotation != null && alan.label - .equals(annotation.label))) + && (alan.label != null && annotation != null + && alan.label.equals(annotation.label))) { + if (!rna && alan.isRNA()) + { + rna = true; + } seqannot.put(alan.sequenceRef, alan); + if (f || alan.graphMax > aamax) + { + aamax = alan.graphMax; + } + if (f || alan.graphMin < aamin) + { + aamin = alan.graphMin; + } + f = false; } } + if (rna) + { + ColourSchemeProperty.initRnaHelicesShading(1 + (int) aamax); + } } } - public String getAnnotation() + float aamin = 0f, aamax = 0f; + + public AlignmentAnnotation getAnnotation() { - return annotation.label; + return annotation; } public int getAboveThreshold() @@ -177,12 +248,13 @@ public class AnnotationColourGradient extends FollowerColourScheme public Color getMinColour() { - return new Color((int) r1, (int) g1, (int) b1); + return new Color(redMin, greenMin, blueMin); } public Color getMaxColour() { - return new Color((int) (r1 + rr), (int) (g1 + gg), (int) (b1 + bb)); + return new Color(redMin + redRange, greenMin + greenRange, + blueMin + blueRange); } /** @@ -193,97 +265,184 @@ public class AnnotationColourGradient extends FollowerColourScheme * * @return DOCUMENT ME! */ + @Override public Color findColour(char c) { return Color.red; } /** - * DOCUMENT ME! + * Returns the colour for a given character and position in a sequence * - * @param n - * DOCUMENT ME! + * @param c + * the residue character * @param j - * DOCUMENT ME! - * - * @return DOCUMENT ME! + * the aligned position + * @param seq + * the sequence + * @return */ @Override public Color findColour(char c, int j, SequenceI seq) { - Color currentColour = Color.white; - AlignmentAnnotation annotation = (seqAssociated ? seqannot.get(seq) + /* + * locate the annotation we are configured to colour by + */ + AlignmentAnnotation ann = (seqAssociated && seqannot != null + ? seqannot.get(seq) : this.annotation); - if (annotation == null) + + /* + * if gap or no annotation at position, no colour (White) + */ + if (ann == null || ann.annotations == null + || j >= ann.annotations.length || ann.annotations[j] == null + || Comparison.isGap(c)) { - return currentColour; + return Color.white; } - if ((threshold == 0) || aboveThreshold(c, j)) + + Annotation aj = ann.annotations[j]; + // 'use original colours' => colourScheme != null + // -> look up colour to be used + // predefined colours => preconfigured shading + // -> only use original colours reference if thresholding enabled & + // minmax exists + // annotation.hasIcons => null or black colours replaced with glyph + // colours + // -> reuse original colours if present + // -> if thresholding enabled then return colour on non-whitespace glyph + + /* + * if threshold applies, and annotation fails the test - no colour (white) + */ + if (annotationThreshold != null) { - if (annotation.annotations!=null && j < annotation.annotations.length - && annotation.annotations[j] != null - && !jalview.util.Comparison.isGap(c)) + if ((aboveAnnotationThreshold == ABOVE_THRESHOLD + && aj.value < annotationThreshold.value) + || (aboveAnnotationThreshold == BELOW_THRESHOLD + && aj.value > annotationThreshold.value)) { + return Color.white; + } + } + + /* + * If 'use original colours' then return the colour of the annotation + * at the aligned position - computed using the background colour scheme + */ + if (predefinedColours && aj.colour != null + && !aj.colour.equals(Color.black)) + { + return aj.colour; + } - if (predefinedColours) + Color result = Color.white; + if (ann.hasIcons && ann.graph == AlignmentAnnotation.NO_GRAPH) + { + /* + * secondary structure symbol colouring + */ + if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.' + && aj.secondaryStructure != '-') + { + if (getColourScheme() != null) { - if (annotation.annotations[j].colour != null) - return annotation.annotations[j].colour; - else - return currentColour; + result = getColourScheme().findColour(c, j, seq, null, 0f); } - - if (aboveAnnotationThreshold == NO_THRESHOLD - || (annotationThreshold != null - && aboveAnnotationThreshold == ABOVE_THRESHOLD && annotation.annotations[j].value >= annotationThreshold.value) - || (annotationThreshold != null - && aboveAnnotationThreshold == BELOW_THRESHOLD && annotation.annotations[j].value <= annotationThreshold.value)) + else { - - float range = 1f; - if (thresholdIsMinMax - && annotation.threshold != null - && aboveAnnotationThreshold == ABOVE_THRESHOLD - && annotation.annotations[j].value >= annotation.threshold.value) - { - range = (annotation.annotations[j].value - annotation.threshold.value) - / (annotation.graphMax - annotation.threshold.value); - } - else if (thresholdIsMinMax && annotation.threshold != null - && aboveAnnotationThreshold == BELOW_THRESHOLD - && annotation.annotations[j].value >= annotation.graphMin) + if (ann.isRNA()) { - range = (annotation.annotations[j].value - annotation.graphMin) - / (annotation.threshold.value - annotation.graphMin); + result = ColourSchemeProperty.rnaHelices[(int) aj.value]; } else { - range = (annotation.annotations[j].value - annotation.graphMin) - / (annotation.graphMax - annotation.graphMin); - } - - if (colourScheme != null) - { - currentColour = colourScheme.findColour(c, j, seq); - } - else - { - dr = rr * range + r1; - dg = gg * range + g1; - db = bb * range + b1; - - currentColour = new Color((int) dr, (int) dg, (int) db); + result = ann.annotations[j].secondaryStructure == 'H' + ? AnnotationRenderer.HELIX_COLOUR + : ann.annotations[j].secondaryStructure == 'E' + ? AnnotationRenderer.SHEET_COLOUR + : AnnotationRenderer.STEM_COLOUR; } } } + else + { + return Color.white; + } } + else if (noGradient) + { + if (getColourScheme() != null) + { + result = getColourScheme().findColour(c, j, seq, null, 0f); + } + else + { + if (aj.colour != null) + { + result = aj.colour; + } + } + } + else + { + result = shadeCalculation(ann, j); + } + + return result; + } - if (conservationColouring) + /** + * Returns a graduated colour for the annotation at the given column. If there + * is a threshold value, and it is used as the top/bottom of the colour range, + * and the value satisfies the threshold condition, then a colour + * proportionate to the range from the threshold is calculated. For all other + * cases, a colour proportionate to the annotation's min-max range is + * calulated. Note that thresholding is _not_ done here (a colour is computed + * even if threshold is not passed). + * + * @param ann + * @param col + * @return + */ + Color shadeCalculation(AlignmentAnnotation ann, int col) + { + float range = 1f; + float value = ann.annotations[col].value; + if (thresholdIsMinMax && ann.threshold != null + && aboveAnnotationThreshold == ABOVE_THRESHOLD + && value >= ann.threshold.value) { - currentColour = applyConservation(currentColour, j); + range = ann.graphMax == ann.threshold.value ? 1f + : (value - ann.threshold.value) + / (ann.graphMax - ann.threshold.value); + } + else if (thresholdIsMinMax && ann.threshold != null + && aboveAnnotationThreshold == BELOW_THRESHOLD + && value <= ann.threshold.value) + { + range = ann.graphMin == ann.threshold.value ? 0f + : (value - ann.graphMin) + / (ann.threshold.value - ann.graphMin); + } + else + { + if (ann.graphMax != ann.graphMin) + { + range = (value - ann.graphMin) / (ann.graphMax - ann.graphMin); + } + else + { + range = 0f; + } } - return currentColour; + int dr = (int) (redRange * range + redMin); + int dg = (int) (greenRange * range + greenMin); + int db = (int) (blueRange * range + blueMin); + + return new Color(dr, dg, db); } public boolean isPredefinedColours() @@ -305,4 +464,26 @@ public class AnnotationColourGradient extends FollowerColourScheme { seqAssociated = sassoc; } + + public boolean isThresholdIsMinMax() + { + return thresholdIsMinMax; + } + + public void setThresholdIsMinMax(boolean minMax) + { + this.thresholdIsMinMax = minMax; + } + + @Override + public String getSchemeName() + { + return "Annotation"; + } + + @Override + public boolean isSimple() + { + return false; + } }