quantitative shading of features by GraduatedColor
authorjprocter <Jim Procter>
Tue, 17 Mar 2009 17:00:20 +0000 (17:00 +0000)
committerjprocter <Jim Procter>
Tue, 17 Mar 2009 17:00:20 +0000 (17:00 +0000)
src/jalview/gui/FeatureRenderer.java

index b6806e7..ade8915 100755 (executable)
@@ -29,6 +29,7 @@ import java.beans.PropertyChangeSupport;
 import javax.swing.*;
 
 import jalview.datamodel.*;
+import jalview.schemes.GraduatedColor;
 
 /**
  * DOCUMENT ME!
@@ -43,6 +44,7 @@ public class FeatureRenderer
   AlignViewport av;
 
   Color resBoxColour;
+
   /**
    * global transparency for feature
    */
@@ -253,7 +255,7 @@ public class FeatureRenderer
   /**
    * show scores as heights
    */
-  protected boolean varyHeight=false;
+  protected boolean varyHeight = false;
 
   synchronized public void drawSequence(Graphics g, SequenceI seq,
           int start, int end, int y1)
@@ -373,19 +375,26 @@ public class FeatureRenderer
 
         }
         else
-       if (av.showSeqFeaturesHeight && sequenceFeatures[sfindex].score!=Float.NaN)
-        {
-         renderScoreFeature(g, seq, seq
-                 .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
-                 .findIndex(sequenceFeatures[sfindex].end) - 1,
-                 getColour(sequenceFeatures[sfindex].type), start, end, y1, normaliseScore(sequenceFeatures[sfindex]));
-        } else
-        {
-          renderFeature(g, seq, seq
-                  .findIndex(sequenceFeatures[sfindex].begin) - 1, seq
-                  .findIndex(sequenceFeatures[sfindex].end) - 1,
-                  getColour(sequenceFeatures[sfindex].type), start, end, y1);
-        }
+          if (showFeature(sequenceFeatures[sfindex]))
+          {
+              if (av.showSeqFeaturesHeight
+                      && sequenceFeatures[sfindex].score != Float.NaN)
+              {
+                renderScoreFeature(g, seq, seq
+                        .findIndex(sequenceFeatures[sfindex].begin) - 1,
+                        seq.findIndex(sequenceFeatures[sfindex].end) - 1,
+                        getColour(sequenceFeatures[sfindex]), start, end,
+                        y1, normaliseScore(sequenceFeatures[sfindex]));
+              }
+              else
+              {
+                renderFeature(g, seq, seq
+                        .findIndex(sequenceFeatures[sfindex].begin) - 1,
+                        seq.findIndex(sequenceFeatures[sfindex].end) - 1,
+                        getColour(sequenceFeatures[sfindex]), start, end,
+                        y1);
+              }
+          }
 
       }
 
@@ -398,24 +407,31 @@ public class FeatureRenderer
               1.0f));
     }
   }
+
   Hashtable minmax = new Hashtable();
+
   /**
    * normalise a score against the max/min bounds for the feature type.
+   * 
    * @param sequenceFeature
-   * @return byte[] { signed, normalised signed (-127 to 127) or unsigned (0-255) value.
+   * @return byte[] { signed, normalised signed (-127 to 127) or unsigned
+   *         (0-255) value.
    */
   private final byte[] normaliseScore(SequenceFeature sequenceFeature)
   {
-    float[] mm = (float[]) minmax.get(sequenceFeature.type);
-    final byte[] r=new byte[] { 0, (byte) 255};
-    if (mm!=null)
+    float[] mm = ((float[][]) minmax.get(sequenceFeature.type))[0];
+    final byte[] r = new byte[]
+    { 0, (byte) 255 };
+    if (mm != null)
     {
-      if (r[0]!=0 || mm[0]<0.0)
+      if (r[0] != 0 || mm[0] < 0.0)
       {
-        r[0]=1;
-        r[1]=(byte) ((int) 128.0+127.0*(sequenceFeature.score/mm[1]));
-      } else {
-        r[1]=(byte) ((int) 255.0*(sequenceFeature.score/mm[1]));
+        r[0] = 1;
+        r[1] = (byte) ((int) 128.0 + 127.0 * (sequenceFeature.score / mm[1]));
+      }
+      else
+      {
+        r[1] = (byte) ((int) 255.0 * (sequenceFeature.score / mm[1]));
       }
     }
     return r;
@@ -468,6 +484,7 @@ public class FeatureRenderer
       }
     }
   }
+
   void renderScoreFeature(Graphics g, SequenceI seq, int fstart, int fend,
           Color featureColour, int start, int end, int y1, byte[] bs)
   {
@@ -484,21 +501,25 @@ public class FeatureRenderer
         fend = end;
       }
       int pady = (y1 + av.charHeight) - av.charHeight / 5;
-      int ystrt = 0,yend=av.charHeight;
-      if (bs[0]!=0)
+      int ystrt = 0, yend = av.charHeight;
+      if (bs[0] != 0)
       {
         // signed - zero is always middle of residue line.
-        if (bs[1]<128)
+        if (bs[1] < 128)
         {
-          yend = av.charHeight*(128-bs[1])/512;
-          ystrt = av.charHeight-yend/2;
-        } else {
-          ystrt = av.charHeight/2;
-          yend = av.charHeight*(bs[1]-128)/512;
+          yend = av.charHeight * (128 - bs[1]) / 512;
+          ystrt = av.charHeight - yend / 2;
         }
-      } else {
-        yend = av.charHeight*bs[1]/255;
-        ystrt = av.charHeight-yend;
+        else
+        {
+          ystrt = av.charHeight / 2;
+          yend = av.charHeight * (bs[1] - 128) / 512;
+        }
+      }
+      else
+      {
+        yend = av.charHeight * bs[1] / 255;
+        ystrt = av.charHeight - yend;
 
       }
       for (i = fstart; i <= fend; i++)
@@ -511,10 +532,9 @@ public class FeatureRenderer
         }
 
         g.setColor(featureColour);
-        int x=(i-start)*av.charWidth;
+        int x = (i - start) * av.charWidth;
         g.drawRect(x, y1, av.charWidth, av.charHeight);
-        g.fillRect(x, y1+ystrt, av.charWidth,
-                yend);
+        g.fillRect(x, y1 + ystrt, av.charWidth, yend);
 
         if (offscreenRender || !av.validCharWidth)
         {
@@ -600,7 +620,7 @@ public class FeatureRenderer
         }
       }
     }
-    if (minmax==null)
+    if (minmax == null)
     {
       minmax = new Hashtable();
     }
@@ -653,21 +673,29 @@ public class FeatureRenderer
         {
           allfeatures.addElement(features[index].getType());
         }
-        if (features[index].score!=Float.NaN)
-        { 
-          float[] mm = (float[]) minmax.get(features[index].getType());
-          if (mm==null)
+        if (features[index].score != Float.NaN)
+        {
+          int nonpos= features[index].getBegin()>=1 ? 0 : 1;
+          float[][] mm = (float[][]) minmax.get(features[index].getType());
+          if (mm == null)
           {
-            mm = new float[] { features[index].score,features[index].score};
+            mm = new float[][] {null, null };
             minmax.put(features[index].getType(), mm);
-          } else {
-            if (mm[0]>features[index].score)
+          }
+          if (mm[nonpos]==null)
+          { 
+            mm[nonpos] = new float[] { features[index].score, features[index].score };
+            
+          }
+          else
+          {
+            if (mm[nonpos][0] > features[index].score)
             {
-              mm[0] = features[index].score;
+              mm[nonpos][0] = features[index].score;
             }
-            if (mm[1]<features[index].score)
+            if (mm[nonpos][1] < features[index].score)
             {
-              mm[1] = features[index].score;
+              mm[nonpos][1] = features[index].score;
             }
           }
         }
@@ -756,16 +784,68 @@ public class FeatureRenderer
 
   public Color getColour(String featureType)
   {
-    if (!featureColours.containsKey(featureType))
+    Object fc = featureColours.get(featureType);
+    if (fc == null)
     {
       jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
       Color col = ucs.createColourFromName(featureType);
       featureColours.put(featureType, col);
       return col;
     }
+    else if (fc instanceof Color)
+    {
+      return (Color) fc;
+    }
     else
-      return (Color) featureColours.get(featureType);
+    {
+      if (fc instanceof GraduatedColor)
+      {
+        return ((GraduatedColor) fc).getMinColor();
+      }
+      // TODO: raise an implementation error here.
+      return null; // Color.white;
+    }
+  }
+
+  /**
+   * implement graduated colouring for features with scores
+   * 
+   * @param feature
+   * @return render colour for the given feature
+   */
+  public Color getColour(SequenceFeature feature)
+  {
+    Object fc = featureColours.get(feature.type);
+    if (fc == null)
+    {
+      jalview.schemes.UserColourScheme ucs = new jalview.schemes.UserColourScheme();
+      Color col = ucs.createColourFromName(feature.type);
+      featureColours.put(feature.type, col);
+      return col;
+    }
+    else if (fc instanceof Color)
+    {
+      return (Color) fc;
+    }
+    else
+    {
+      if (fc instanceof GraduatedColor)
+      {
+        return ((GraduatedColor) fc).findColor(feature);
+      }
+      // TODO: raise an implementation error here.
+      return null; // Color.white;
+    }
   }
+  private boolean showFeature(SequenceFeature sequenceFeature)
+  {
+    Object fc = featureColours.get(sequenceFeature.type);
+    if (fc instanceof GraduatedColor)
+    {
+      return ((GraduatedColor) fc).isColored(sequenceFeature);
+    } else { return true; }
+  }
+
 
   static String lastFeatureAdded;
 
@@ -799,6 +879,7 @@ public class FeatureRenderer
     {
       public void mousePressed(MouseEvent evt)
       {
+        // TODO: use featurecolourchooser here
         Color col = JColorChooser.showDialog(Desktop.desktop,
                 "Select Feature Colour", colour.getBackground());
         if (col != null)
@@ -1058,7 +1139,11 @@ public class FeatureRenderer
 
   public void setColour(String featureType, Color col)
   {
-    featureColours.put(featureType, col);
+    Object c = featureColours.get(featureType);
+    if (c == null || c instanceof Color || (c instanceof GraduatedColor && !((GraduatedColor)c).getMaxColor().equals(col)))
+    {
+      featureColours.put(featureType, col);
+    }
   }
 
   public void setTransparency(float value)