JAL-1958 modulate per-sequence shading with local score - low scores tend to grey.
[jalview.git] / src / jalview / schemes / AnnotationColourGradient.java
index 3cada8b..b580be2 100755 (executable)
@@ -1,6 +1,6 @@
 /*
- * 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.
  * 
@@ -34,6 +34,16 @@ import java.util.Map;
 
 public class AnnotationColourGradient extends FollowerColourScheme
 {
+  /**
+   * map positional scores to transparency rather than colour
+   */
+  boolean positionToTransparency = true;
+
+  /**
+   * compute shade based on annotation row score
+   */
+  boolean perLineScore = true;
+
   public static final int NO_THRESHOLD = -1;
 
   public static final int BELOW_THRESHOLD = 0;
@@ -53,12 +63,14 @@ public class AnnotationColourGradient extends FollowerColourScheme
   private boolean predefinedColours = false;
 
   private boolean seqAssociated = false;
+
   /**
    * 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;
+
   IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
 
   @Override
@@ -79,6 +91,8 @@ public class AnnotationColourGradient extends FollowerColourScheme
     acg.predefinedColours = predefinedColours;
     acg.seqAssociated = seqAssociated;
     acg.noGradient = noGradient;
+    acg.positionToTransparency = positionToTransparency;
+    acg.perLineScore = perLineScore;
     return acg;
   }
 
@@ -114,6 +128,7 @@ public class AnnotationColourGradient extends FollowerColourScheme
     bb = 0;
 
     noGradient = true;
+    checkLimits();
   }
 
   /**
@@ -140,10 +155,17 @@ public class AnnotationColourGradient extends FollowerColourScheme
     bb = maxColour.getBlue() - b1;
 
     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);
     }
   }
@@ -167,7 +189,8 @@ public class AnnotationColourGradient extends FollowerColourScheme
       // resolve the context containing all the annotation for the sequence
       AnnotatedCollectionI alcontext = alignment instanceof AlignmentI ? alignment
               : alignment.getContext();
-      boolean f = true,rna=false;
+      boolean f = true, sf = true, rna = false;
+      long plcount = 0, ancount = 0;
       for (AlignmentAnnotation alan : alcontext.findAnnotation(annotation
               .getCalcId()))
       {
@@ -175,6 +198,7 @@ public class AnnotationColourGradient extends FollowerColourScheme
                 && (alan.label != null && annotation != null && alan.label
                         .equals(annotation.label)))
         {
+          ancount++;
           if (!rna && alan.isRNA())
           {
             rna = true;
@@ -189,8 +213,26 @@ public class AnnotationColourGradient extends FollowerColourScheme
             aamin = alan.graphMin;
           }
           f = false;
+          if (alan.score == alan.score)
+          {
+            if (sf || alan.score < plmin)
+            {
+              plmin = alan.score;
+            }
+            if (sf || alan.score > plmax)
+            {
+              plmax = alan.score;
+            }
+            sf = false;
+            plcount++;
+          }
         }
       }
+      if (plcount > 0 && plcount == ancount)
+      {
+        perLineScore = plcount == ancount;
+        aamax=plmax;
+      }
       if (rna)
       {
         ColourSchemeProperty.initRnaHelicesShading(1 + (int) aamax);
@@ -198,7 +240,16 @@ public class AnnotationColourGradient extends FollowerColourScheme
     }
   }
 
-  float aamin = 0f, aamax = 0f;
+  /**
+   * positional annotation max/min
+   */
+  double aamin = 0.0, aamax = 0.0;
+
+  /**
+   * per line score max/min
+   */
+  double plmin = Double.NaN, plmax = Double.NaN;
+
   public String getAnnotation()
   {
     return annotation.label;
@@ -239,6 +290,7 @@ public class AnnotationColourGradient extends FollowerColourScheme
    * 
    * @return DOCUMENT ME!
    */
+  @Override
   public Color findColour(char c)
   {
     return Color.red;
@@ -258,8 +310,8 @@ public class AnnotationColourGradient extends FollowerColourScheme
   public Color findColour(char c, int j, SequenceI seq)
   {
     Color currentColour = Color.white;
-    AlignmentAnnotation annotation = (seqAssociated ? seqannot.get(seq)
-            : this.annotation);
+    AlignmentAnnotation annotation = (seqAssociated && seqannot != null ? seqannot
+            .get(seq) : this.annotation);
     if (annotation == null)
     {
       return currentColour;
@@ -286,7 +338,8 @@ public class AnnotationColourGradient extends FollowerColourScheme
                 || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value
                         : aj.value <= annotationThreshold.value)))
         {
-          if (predefinedColours && aj.colour != null)
+          if (predefinedColours && aj.colour != null
+                  && !aj.colour.equals(Color.black))
           {
             currentColour = aj.colour;
           }
@@ -380,13 +433,26 @@ public class AnnotationColourGradient extends FollowerColourScheme
         range = 0f;
       }
     }
-
+    // midtr sets the ceiling for bleaching out the shading
+    int trans = 0, midtr = 239;
+    if (perLineScore)
+    {
+      trans = (int) ((1f - range) * midtr);
+      range = (float) ((annotation.score - plmin) / (plmax - aamin));
+    }
     int dr = (int) (rr * range + r1), dg = (int) (gg * range + g1), db = (int) (bb
             * range + b1);
-
-    return new Color(dr, dg, db);
-
+    if (annotation.score == annotation.score && positionToTransparency)
+    {
+      return new Color(Integer.min(dr + trans, midtr), Integer.min(dg
+              + trans, midtr), Integer.min(db + trans, midtr));
+    }
+    else
+    {
+      return new Color(dr, dg, db);
+    }
   }
+
   public boolean isPredefinedColours()
   {
     return predefinedColours;