Merge branch 'develop' into bug/JAL-2346annotationChoice
authorgmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 14 Feb 2017 12:34:54 +0000 (12:34 +0000)
committergmungoc <g.m.carstairs@dundee.ac.uk>
Tue, 14 Feb 2017 12:34:54 +0000 (12:34 +0000)
Conflicts:
src/jalview/appletgui/AnnotationColourChooser.java
src/jalview/gui/AnnotationRowFilter.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/PopupMenu.java
src/jalview/schemes/AnnotationColourGradient.java

1  2 
src/jalview/appletgui/AnnotationColourChooser.java
src/jalview/gui/AnnotationColourChooser.java
src/jalview/gui/AnnotationRowFilter.java
src/jalview/gui/Jalview2XML.java
src/jalview/gui/PopupMenu.java
src/jalview/schemes/AnnotationColourGradient.java

@@@ -40,16 -46,9 +46,10 @@@ import java.awt.event.ItemEvent
  import java.awt.event.ItemListener;
  import java.awt.event.MouseEvent;
  import java.awt.event.MouseListener;
 -import java.util.Hashtable;
 +import java.util.HashMap;
 +import java.util.Map;
  import java.util.Vector;
  
- import jalview.datamodel.AlignmentAnnotation;
- import jalview.datamodel.SequenceGroup;
- import jalview.schemes.AnnotationColourGradient;
- import jalview.schemes.ColourSchemeI;
- import jalview.util.MessageManager;
  public class AnnotationColourChooser extends Panel implements
          ActionListener, AdjustmentListener, ItemListener, MouseListener
  {
      oldcs = av.getGlobalColourScheme();
      if (av.getAlignment().getGroups() != null)
      {
 -      oldgroupColours = new Hashtable();
 +      oldgroupColours = new HashMap<SequenceGroup, ColourSchemeI>();
        for (SequenceGroup sg : ap.av.getAlignment().getGroups())
        {
-         if (sg.cs != null)
-         {
-           oldgroupColours.put(sg, sg.cs);
-         }
 -        if (sg.getColourScheme() != null)
 -        {
 -          oldgroupColours.put(sg, sg.getColourScheme());
 -        }
 -        else
 -        {
 -          oldgroupColours.put(sg, "null");
 -        }
++        oldgroupColours.put(sg, sg.getColourScheme());
        }
      }
      this.av = av;
      {
        for (SequenceGroup sg : ap.av.getAlignment().getGroups())
        {
-         if (sg.cs == null)
 -
+         if (sg.getColourScheme() == null)
          {
            continue;
          }
          }
          else
          {
-           sg.cs = new AnnotationColourGradient(currentAnnotation,
-                   minColour.getBackground(), maxColour.getBackground(),
-                   aboveThreshold);
+           sg.setColourScheme(new AnnotationColourGradient(
+                   currentAnnotation, minColour.getBackground(), maxColour
+                           .getBackground(), aboveThreshold));
          }
 -
        }
      }
  
      {
        for (SequenceGroup sg : ap.av.getAlignment().getGroups())
        {
-         sg.cs = oldgroupColours.get(sg);
 -        Object cs = oldgroupColours.get(sg);
 -        if (cs instanceof ColourSchemeI)
 -        {
 -          sg.setColourScheme((ColourSchemeI) cs);
 -        }
 -        else
 -        {
 -          // probably the "null" string we set it to if it was null originally.
 -          sg.setColourScheme(null);
 -        }
++        sg.setColourScheme(oldgroupColours.get(sg));
        }
      }
      ap.paintAlignment(true);
--
    }
  
    @Override
@@@ -412,60 -483,4 +412,60 @@@ public class AnnotationColourChooser ex
      ap.paintAlignment(true);
    }
  
 +  protected boolean colorAlignmentContaining(AlignmentAnnotation currentAnn, int selectedThresholdOption)
 +  {
 +  
 +    AnnotationColourGradient acg = null;
 +    if (currentColours.isSelected())
 +    {
 +      acg = new AnnotationColourGradient(currentAnn,
 +              av.getGlobalColourScheme(), selectedThresholdOption);
 +    }
 +    else
 +    {
 +      acg = new AnnotationColourGradient(currentAnn,
 +              minColour.getBackground(), maxColour.getBackground(),
 +              selectedThresholdOption);
 +    }
 +    acg.setSeqAssociated(seqAssociated.isSelected());
 +  
 +    if (currentAnn.graphMin == 0f && currentAnn.graphMax == 0f)
 +    {
 +      acg.setPredefinedColours(true);
 +    }
 +  
 +    acg.setThresholdIsMinMax(thresholdIsMin.isSelected());
 +  
 +    av.setGlobalColourScheme(acg);
 +  
 +    if (av.getAlignment().getGroups() != null)
 +    {
 +  
 +      for (SequenceGroup sg : ap.av.getAlignment().getGroups())
 +      {
 +        if (sg.cs == null)
 +        {
 +          continue;
 +        }
 +  
 +        if (currentColours.isSelected())
 +        {
-           sg.cs = new AnnotationColourGradient(currentAnn, sg.cs,
-                   selectedThresholdOption);
++          sg.setColourScheme(new AnnotationColourGradient(currentAnn, sg
++                  .getColourScheme(), selectedThresholdOption));
 +          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
 +                  .isSelected());
 +        }
 +        else
 +        {
-           sg.cs = new AnnotationColourGradient(currentAnn,
++          sg.setColourScheme(new AnnotationColourGradient(currentAnn,
 +                  minColour.getBackground(), maxColour.getBackground(),
-                   selectedThresholdOption);
++                  selectedThresholdOption));
 +          ((AnnotationColourGradient) sg.cs).setSeqAssociated(seqAssociated
 +                  .isSelected());
 +        }
 +      }
 +    }
 +    return false;
 +  }
 +
  }
@@@ -58,7 -49,17 +58,13 @@@ public abstract class AnnotationRowFilt
  
    protected int[] annmap;
  
 -  protected boolean enableSeqAss = false;
 -
 -  private AlignmentAnnotation currentAnnotation;
 -
    protected boolean adjusting = false;
 -
++  
+   protected JCheckBox currentColours = new JCheckBox();
+   protected JPanel minColour = new JPanel();
+   protected JPanel maxColour = new JPanel();
  
    protected JCheckBox seqAssociated = new JCheckBox();
  
      }
    }
  
-   protected AlignmentAnnotation getCurrentAnnotation()
 -  protected boolean colorAlignmContaining(AlignmentAnnotation currentAnn,
 -          int selectedThresholdOption)
++  public AlignmentAnnotation getCurrentAnnotation()
    {
 +    return currentAnnotation;
 +  }
  
 -    AnnotationColourGradient acg = null;
 -    if (currentColours.isSelected())
 -    {
 -      acg = new AnnotationColourGradient(currentAnn,
 -              av.getGlobalColourScheme(), selectedThresholdOption);
 -    }
 -    else
 -    {
 -      acg = new AnnotationColourGradient(currentAnn,
 -              minColour.getBackground(), maxColour.getBackground(),
 -              selectedThresholdOption);
 -    }
 -    acg.setSeqAssociated(seqAssociated.isSelected());
 +  protected void setCurrentAnnotation(AlignmentAnnotation currentAnnotation)
 +  {
 +    this.currentAnnotation = currentAnnotation;
 +  }
  
 -    if (currentAnn.graphMin == 0f && currentAnn.graphMax == 0f)
 -    {
 -      acg.setPredefinedColours(true);
 -    }
 +  protected abstract void valueChanged(boolean updateAllAnnotation);
  
 -    acg.thresholdIsMinMax = thresholdIsMin.isSelected();
 +  protected abstract void updateView();
  
 -    av.setGlobalColourScheme(acg);
 +  protected abstract void reset();
  
 -    if (av.getAlignment().getGroups() != null)
 +  protected String getAnnotationMenuLabel(AlignmentAnnotation ann)
 +  {
 +    return annotationLabels.get(ann);
 +  }
 +
 +  protected void jbInit()
 +  {
 +    ok.setOpaque(false);
 +    ok.setText(MessageManager.getString("action.ok"));
 +    ok.addActionListener(new ActionListener()
      {
 +      @Override
 +      public void actionPerformed(ActionEvent e)
 +      {
 +        ok_actionPerformed();
 +      }
 +    });
  
 -      for (SequenceGroup sg : ap.av.getAlignment().getGroups())
 +    cancel.setOpaque(false);
 +    cancel.setText(MessageManager.getString("action.cancel"));
 +    cancel.addActionListener(new ActionListener()
 +    {
 +      @Override
 +      public void actionPerformed(ActionEvent e)
        {
 -        if (sg.cs == null)
 -        {
 -          continue;
 -        }
 +        cancel_actionPerformed();
 +      }
 +    });
  
 -        AnnotationColourGradient scheme = null;
 -        if (currentColours.isSelected())
 -        {
 -          scheme = new AnnotationColourGradient(currentAnn,
 -                  sg.getColourScheme(), selectedThresholdOption);
 -        }
 -        else
 -        {
 -          scheme = new AnnotationColourGradient(currentAnn,
 -                  minColour.getBackground(), maxColour.getBackground(),
 -                  selectedThresholdOption);
 -        }
 -        scheme.setSeqAssociated(seqAssociated.isSelected());
 -        sg.setColourScheme(scheme);
 +    annotations.addItemListener(new ItemListener()
 +    {
 +      @Override
 +      public void itemStateChanged(ItemEvent e)
 +      {
 +        selectedAnnotationChanged();
        }
 -    }
 -    return false;
 +    });
 +    annotations.setToolTipText(MessageManager
 +            .getString("info.select_annotation_row"));
 +
 +    threshold.addActionListener(new ActionListener()
 +    {
 +      @Override
 +      public void actionPerformed(ActionEvent e)
 +      {
 +        threshold_actionPerformed();
 +      }
 +    });
 +
 +    thresholdValue.setEnabled(false);
 +    thresholdValue.setColumns(7);
 +    thresholdValue.addActionListener(new ActionListener()
 +    {
 +      @Override
 +      public void actionPerformed(ActionEvent e)
 +      {
 +        thresholdValue_actionPerformed();
 +      }
 +    });
 +
 +    slider.setPaintLabels(false);
 +    slider.setPaintTicks(true);
 +    slider.setBackground(Color.white);
 +    slider.setEnabled(false);
 +    slider.setOpaque(false);
 +    slider.setPreferredSize(new Dimension(100, 32));
    }
  
 -  public jalview.datamodel.AlignmentAnnotation getCurrentAnnotation()
 +  public JComboBox<String> getThreshold()
    {
 -    return currentAnnotation;
 +    return threshold;
    }
  
 -  public void setCurrentAnnotation(
 -          jalview.datamodel.AlignmentAnnotation currentAnnotation)
 +  public void setThreshold(JComboBox<String> thresh)
    {
 -    this.currentAnnotation = currentAnnotation;
 +    this.threshold = thresh;
    }
  
 -  public abstract void valueChanged(boolean updateAllAnnotation);
 -
 -  public abstract void updateView();
 +  public JComboBox<String> getAnnotations()
 +  {
 +    return annotations;
 +  }
  
 -  public abstract void reset();
 +  public void setAnnotations(JComboBox<String> anns)
 +  {
 +    this.annotations = anns;
 +  }
  }
@@@ -110,7 -77,7 +78,6 @@@ import jalview.schemes.AnnotationColour
  import jalview.schemes.ColourSchemeI;
  import jalview.schemes.ColourSchemeProperty;
  import jalview.schemes.FeatureColour;
--import jalview.schemes.ResidueColourScheme;
  import jalview.schemes.ResidueProperties;
  import jalview.schemes.UserColourScheme;
  import jalview.structure.StructureSelectionManager;
@@@ -1709,6 -1711,6 +1711,15 @@@ public class Jalview2XM
      return matchedFile;
    }
  
++  /**
++   * Populates the AnnotationColours xml for save. This captures the settings of
++   * the options in the 'Colour by Annotation' dialog.
++   * 
++   * @param acg
++   * @param userColours
++   * @param jms
++   * @return
++   */
    private AnnotationColours constructAnnotationColours(
            AnnotationColourGradient acg, List<UserColourScheme> userColours,
            JalviewModelSequence jms)
      AnnotationColours ac = new AnnotationColours();
      ac.setAboveThreshold(acg.getAboveThreshold());
      ac.setThreshold(acg.getAnnotationThreshold());
 -    ac.setAnnotation(acg.getAnnotation());
 -    if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
 +    // 2.10.2 save annotationId (unique) not annotation label
 +    ac.setAnnotation(acg.getAnnotation().annotationId);
-     if (acg.getBaseColour() instanceof jalview.schemes.UserColourScheme)
++    if (acg.getBaseColour() instanceof UserColourScheme)
      {
        ac.setColourScheme(setUserColourScheme(acg.getBaseColour(),
                userColours, jms));
      return af;
    }
  
++  /**
++   * Reads saved data to restore Colour by Annotation settings
++   * 
++   * @param viewAnnColour
++   * @param af
++   * @param al
++   * @param jms
++   * @param checkGroupAnnColour
++   * @return
++   */
    private ColourSchemeI constructAnnotationColour(
            AnnotationColours viewAnnColour, AlignFrame af, AlignmentI al,
            JalviewModelSequence jms, boolean checkGroupAnnColour)
    {
      boolean propagateAnnColour = false;
-     AnnotationColourGradient cs = null;
 -    ColourSchemeI cs = null;
      AlignmentI annAlignment = af != null ? af.viewport.getAlignment() : al;
      if (checkGroupAnnColour && al.getGroups() != null
              && al.getGroups().size() > 0)
        // pre 2.8.1 behaviour
        // check to see if we should transfer annotation colours
        propagateAnnColour = true;
 -      for (jalview.datamodel.SequenceGroup sg : al.getGroups())
 +      for (SequenceGroup sg : al.getGroups())
        {
-         if (sg.cs instanceof AnnotationColourGradient)
+         if (sg.getColourScheme() instanceof AnnotationColourGradient)
          {
            propagateAnnColour = false;
          }
        }
      }
 -    // int find annotation
 -    if (annAlignment.getAlignmentAnnotation() != null)
 +
 +    /*
-      * pre 2.10.2: annotationId is AlignmentAnnotation.label
-      * 2.10.2- : annotationId is AlignmentAnnotation.annotationId
++     * 2.10.2- : saved annotationId is AlignmentAnnotation.annotationId
 +     */
 +    String annotationId = viewAnnColour.getAnnotation();
-     AlignmentAnnotation annotation = annotationIds.get(annotationId);
++    AlignmentAnnotation matchedAnnotation = annotationIds.get(annotationId);
 +
-     if (annotation == null && annAlignment.getAlignmentAnnotation() != null)
++    /*
++     * pre 2.10.2: saved annotationId is AlignmentAnnotation.label
++     */
++    if (matchedAnnotation == null && annAlignment.getAlignmentAnnotation() != null)
      {
        for (int i = 0; i < annAlignment.getAlignmentAnnotation().length; i++)
        {
 -        if (annAlignment.getAlignmentAnnotation()[i].label
 -                .equals(viewAnnColour.getAnnotation()))
 +        if (annotationId
 +                .equals(annAlignment.getAlignmentAnnotation()[i].label))
          {
-           annotation = annAlignment.getAlignmentAnnotation()[i];
 -          if (annAlignment.getAlignmentAnnotation()[i].getThreshold() == null)
 -          {
 -            annAlignment.getAlignmentAnnotation()[i]
 -                    .setThreshold(new jalview.datamodel.GraphLine(
 -                            viewAnnColour.getThreshold(), "Threshold",
 -                            java.awt.Color.black)
 -
 -                    );
 -          }
 -
 -          if (viewAnnColour.getColourScheme().equals(
 -                  ResidueColourScheme.NONE))
 -          {
 -            cs = new AnnotationColourGradient(
 -                    annAlignment.getAlignmentAnnotation()[i],
 -                    new java.awt.Color(viewAnnColour.getMinColour()),
 -                    new java.awt.Color(viewAnnColour.getMaxColour()),
 -                    viewAnnColour.getAboveThreshold());
 -          }
 -          else if (viewAnnColour.getColourScheme().startsWith("ucs"))
 -          {
 -            cs = new AnnotationColourGradient(
 -                    annAlignment.getAlignmentAnnotation()[i],
 -                    getUserColourScheme(jms,
 -                            viewAnnColour.getColourScheme()),
 -                    viewAnnColour.getAboveThreshold());
 -          }
 -          else
 -          {
 -            cs = new AnnotationColourGradient(
 -                    annAlignment.getAlignmentAnnotation()[i],
 -                    ColourSchemeProperty.getColourScheme(al,
 -                            viewAnnColour.getColourScheme()),
 -                    viewAnnColour.getAboveThreshold());
 -          }
 -          if (viewAnnColour.hasPerSequence())
 -          {
 -            ((AnnotationColourGradient) cs).setSeqAssociated(viewAnnColour
 -                    .isPerSequence());
 -          }
 -          if (viewAnnColour.hasPredefinedColours())
 -          {
 -            ((AnnotationColourGradient) cs)
 -                    .setPredefinedColours(viewAnnColour
 -                            .isPredefinedColours());
 -          }
 -          if (propagateAnnColour && al.getGroups() != null)
 -          {
 -            // Also use these settings for all the groups
 -            for (int g = 0; g < al.getGroups().size(); g++)
 -            {
 -              jalview.datamodel.SequenceGroup sg = al.getGroups().get(g);
 -
 -              if (sg.cs == null)
 -              {
 -                continue;
 -              }
++          matchedAnnotation = annAlignment.getAlignmentAnnotation()[i];
 +          break;
 +        }
 +      }
 +    }
-     if (annotation == null)
++    if (matchedAnnotation == null)
 +    {
 +      System.err.println("Failed to match annotation colour scheme for "
 +              + annotationId);
 +      return null;
 +    }
-     if (annotation.getThreshold() == null)
++    if (matchedAnnotation.getThreshold() == null)
 +    {
-       annotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
++      matchedAnnotation.setThreshold(new GraphLine(viewAnnColour.getThreshold(),
 +              "Threshold", Color.black));
 +    }
  
 -              /*
 -               * if (viewAnnColour.getColourScheme().equals(ResidueColourScheme.NONE)) { sg.cs =
 -               * new AnnotationColourGradient(
 -               * annAlignment.getAlignmentAnnotation()[i], new
 -               * java.awt.Color(viewAnnColour. getMinColour()), new
 -               * java.awt.Color(viewAnnColour. getMaxColour()),
 -               * viewAnnColour.getAboveThreshold()); } else
 -               */
 -              {
 -                sg.setColourScheme(new AnnotationColourGradient(
 -                        annAlignment.getAlignmentAnnotation()[i], sg
 -                                .getColourScheme(), viewAnnColour
 -                                .getAboveThreshold()));
 -                if (cs instanceof AnnotationColourGradient)
 -                {
 -                  if (viewAnnColour.hasPerSequence())
 -                  {
 -                    ((AnnotationColourGradient) cs)
 -                            .setSeqAssociated(viewAnnColour.isPerSequence());
 -                  }
 -                  if (viewAnnColour.hasPredefinedColours())
 -                  {
 -                    ((AnnotationColourGradient) cs)
 -                            .setPredefinedColours(viewAnnColour
 -                                    .isPredefinedColours());
 -                  }
 -                }
 -              }
++    AnnotationColourGradient cs = null;
 +    if (viewAnnColour.getColourScheme().equals("None"))
 +    {
-       cs = new AnnotationColourGradient(annotation, new Color(
++      cs = new AnnotationColourGradient(matchedAnnotation, new Color(
 +              viewAnnColour.getMinColour()), new Color(
 +              viewAnnColour.getMaxColour()),
 +              viewAnnColour.getAboveThreshold());
 +    }
 +    else if (viewAnnColour.getColourScheme().startsWith("ucs"))
 +    {
-       cs = new AnnotationColourGradient(annotation, getUserColourScheme(
++      cs = new AnnotationColourGradient(matchedAnnotation, getUserColourScheme(
 +              jms, viewAnnColour.getColourScheme()),
 +              viewAnnColour.getAboveThreshold());
 +    }
 +    else
 +    {
-       cs = new AnnotationColourGradient(annotation,
-               ColourSchemeProperty.getColour(al,
++      cs = new AnnotationColourGradient(matchedAnnotation,
++              ColourSchemeProperty.getColourScheme(al,
 +                      viewAnnColour.getColourScheme()),
 +              viewAnnColour.getAboveThreshold());
 +    }
-     if (viewAnnColour.hasPerSequence())
-     {
-       cs.setSeqAssociated(viewAnnColour.isPerSequence());
-     }
-     if (viewAnnColour.hasPredefinedColours())
-     {
-       cs.setPredefinedColours(viewAnnColour.isPredefinedColours());
-     }
 -            }
 -          }
++    boolean perSequenceOnly = viewAnnColour.isPerSequence();
++    boolean useOriginalColours = viewAnnColour.isPredefinedColours();
++    cs.setSeqAssociated(perSequenceOnly);
++    cs.setPredefinedColours(useOriginalColours);
 -          break;
 +    if (propagateAnnColour && al.getGroups() != null)
 +    {
 +      // Also use these settings for all the groups
 +      for (int g = 0; g < al.getGroups().size(); g++)
 +      {
 +        SequenceGroup sg = al.getGroups().get(g);
-         if (sg.cs == null)
++        if (sg.getGroupColourScheme() == null)
 +        {
 +          continue;
          }
  
-         /*
-          * if (viewAnnColour.getColourScheme().equals("None" )) { sg.cs =
-          * new AnnotationColourGradient(
-          * annAlignment.getAlignmentAnnotation()[i], new
-          * java.awt.Color(viewAnnColour. getMinColour()), new
-          * java.awt.Color(viewAnnColour. getMaxColour()),
-          * viewAnnColour.getAboveThreshold()); } else
-          *
-         {*/
-         sg.cs = new AnnotationColourGradient(annotation, sg.cs,
++        AnnotationColourGradient groupScheme = new AnnotationColourGradient(
++                matchedAnnotation, sg.getColourScheme(),
 +                viewAnnColour.getAboveThreshold());
-         if (cs instanceof AnnotationColourGradient)
-         {
-           if (viewAnnColour.hasPerSequence())
-           {
-             cs.setSeqAssociated(viewAnnColour.isPerSequence());
-           }
-           if (viewAnnColour.hasPredefinedColours())
-           {
-             cs.setPredefinedColours(viewAnnColour.isPredefinedColours());
-           }
-         }
++        sg.setColourScheme(groupScheme);
++        groupScheme.setSeqAssociated(perSequenceOnly);
++        groupScheme.setPredefinedColours(useOriginalColours);
        }
      }
      return cs;
@@@ -51,23 -38,17 +38,16 @@@ import jalview.datamodel.Sequence
  import jalview.datamodel.SequenceFeature;
  import jalview.datamodel.SequenceGroup;
  import jalview.datamodel.SequenceI;
- import jalview.io.FileFormat;
+ import jalview.gui.ColourMenuHelper.ColourChangeListener;
  import jalview.io.FileFormatI;
+ import jalview.io.FileFormats;
  import jalview.io.FormatAdapter;
  import jalview.io.SequenceAnnotationReport;
 -import jalview.schemes.AnnotationColourGradient;
  import jalview.schemes.Blosum62ColourScheme;
- import jalview.schemes.BuriedColourScheme;
- import jalview.schemes.ClustalxColourScheme;
- import jalview.schemes.HelixColourScheme;
- import jalview.schemes.HydrophobicColourScheme;
- import jalview.schemes.NucleotideColourScheme;
+ import jalview.schemes.ColourSchemeI;
+ import jalview.schemes.ColourSchemes;
  import jalview.schemes.PIDColourScheme;
- import jalview.schemes.PurinePyrimidineColourScheme;
- import jalview.schemes.StrandColourScheme;
- import jalview.schemes.TaylorColourScheme;
- import jalview.schemes.TurnColourScheme;
- import jalview.schemes.UserColourScheme;
- import jalview.schemes.ZappoColourScheme;
+ import jalview.schemes.ResidueColourScheme;
  import jalview.util.GroupUrlLink;
  import jalview.util.GroupUrlLink.UrlStringTooLongException;
  import jalview.util.MessageManager;
@@@ -31,6 -27,10 +27,12 @@@ 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;
+ import java.util.Map;
  
  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;
  
-   private boolean thresholdIsMinMax = false;
+   public boolean thresholdIsMinMax = false;
  
 -  GraphLine annotationThreshold;
 +  private GraphLine annotationThreshold;
  
 -  float r1, g1, b1, rr, gg, bb;
 +  private int redMin;
 +
 +  private int greenMin;
 +
 +  private int blueMin;
 +
 +  private int redRange;
 +
 +  private int greenRange;
 +
 +  private int blueRange;
  
    private boolean predefinedColours = false;
  
     */
    private boolean noGradient = false;
  
 -  IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
 +  private IdentityHashMap<SequenceI, AlignmentAnnotation> seqannot = null;
  
    @Override
-   public ColourSchemeI applyTo(AnnotatedCollectionI sg,
+   public ColourSchemeI getInstance(AnnotatedCollectionI sg,
            Map<SequenceI, SequenceCollectionI> hiddenRepSequences)
    {
      AnnotationColourGradient acg = new AnnotationColourGradient(annotation,
    }
  
    /**
--   * 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 != null ? seqannot
++    /*
++     * locate the annotation we are configured to colour by
++     */
 +    AlignmentAnnotation ann = (seqAssociated && seqannot != null ? seqannot
              .get(seq) : this.annotation);
-     if (ann == null)
 -    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))
 -    // if ((threshold == 0) || aboveThreshold(c, j))
 -    // {
 -    if (annotation.annotations != null && j < annotation.annotations.length
 -            && annotation.annotations[j] != null
 -            && !jalview.util.Comparison.isGap(c))
++
++    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 (ann.annotations != null && j < ann.annotations.length
-               && ann.annotations[j] != null
-               && !jalview.util.Comparison.isGap(c))
 -      Annotation aj = annotation.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 (aboveAnnotationThreshold == NO_THRESHOLD
 -              || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value
 -                      : aj.value <= annotationThreshold.value)))
++      if ((aboveAnnotationThreshold == ABOVE_THRESHOLD && aj.value >= annotationThreshold.value)
++              || (aboveAnnotationThreshold == BELOW_THRESHOLD && aj.value > annotationThreshold.value))
        {
-         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 (aboveAnnotationThreshold == NO_THRESHOLD
-                 || (annotationThreshold != null && (aboveAnnotationThreshold == ABOVE_THRESHOLD ? aj.value >= annotationThreshold.value
-                         : aj.value <= annotationThreshold.value)))
 -        if (predefinedColours && aj.colour != null
 -                && !aj.colour.equals(Color.black))
 -        {
 -          currentColour = aj.colour;
 -        }
 -        else if (annotation.hasIcons
 -                && annotation.graph == AlignmentAnnotation.NO_GRAPH)
++        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;
++    }
++
++    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 (predefinedColours && aj.colour != null
-                   && !aj.colour.equals(Color.black))
-           {
-             currentColour = aj.colour;
-           }
-           else if (ann.hasIcons
-                   && ann.graph == AlignmentAnnotation.NO_GRAPH)
-           {
-             if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.'
-                     && aj.secondaryStructure != '-')
-             {
-               if (colourScheme != null)
-               {
-                 currentColour = colourScheme.findColour(c, j, seq);
-               }
-               else
-               {
-                 if (ann.isRNA())
-                 {
-                   currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value];
-                 }
-                 else
-                 {
-                   currentColour = ann.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR
-                           : ann.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR
-                                   : jalview.renderer.AnnotationRenderer.STEM_COLOUR;
-                 }
-               }
-             }
-             else
-             {
-               //
-               return Color.white;
-             }
-           }
-           else if (noGradient)
 -          if (aj.secondaryStructure > ' ' && aj.secondaryStructure != '.'
 -                  && aj.secondaryStructure != '-')
 -          {
 -            if (getColourScheme() != null)
 -            {
 -              currentColour = getColourScheme().findColour(c, j, seq, null,
 -                      0f);
 -            }
 -            else
 -            {
 -              if (annotation.isRNA())
 -              {
 -                currentColour = ColourSchemeProperty.rnaHelices[(int) aj.value];
 -              }
 -              else
 -              {
 -                currentColour = annotation.annotations[j].secondaryStructure == 'H' ? jalview.renderer.AnnotationRenderer.HELIX_COLOUR
 -                        : annotation.annotations[j].secondaryStructure == 'E' ? jalview.renderer.AnnotationRenderer.SHEET_COLOUR
 -                                : jalview.renderer.AnnotationRenderer.STEM_COLOUR;
 -              }
 -            }
 -          }
 -          else
 -          {
 -            //
 -            return Color.white;
 -          }
++          result = getColourScheme().findColour(c, j, seq, null, 0f);
+         }
 -        else if (noGradient)
++        else
+         {
 -          if (getColourScheme() != null)
++          if (ann.isRNA())
            {
-             if (colourScheme != null)
-             {
-               currentColour = colourScheme.findColour(c, j, seq);
-             }
-             else
-             {
-               if (aj.colour != null)
-               {
-                 currentColour = aj.colour;
-               }
-             }
 -            currentColour = getColourScheme().findColour(c, j, seq, null,
 -                    0f);
++            result = ColourSchemeProperty.rnaHelices[(int) aj.value];
            }
            else
            {
-             currentColour = shadeCalculation(ann, j);
 -            if (aj.colour != null)
 -            {
 -              currentColour = aj.colour;
 -            }
++            result = ann.annotations[j].secondaryStructure == 'H' ? AnnotationRenderer.HELIX_COLOUR
++                    : ann.annotations[j].secondaryStructure == 'E' ? AnnotationRenderer.SHEET_COLOUR
++                            : AnnotationRenderer.STEM_COLOUR;
            }
          }
-         if (conservationColouring)
 -        else
++      }
++      else
++      {
++        return Color.white;
++      }
++    }
++    else if (noGradient)
++    {
++      if (getColourScheme() != null)
++      {
++        result = getColourScheme().findColour(c, j, seq, null, 0f);
++      }
++      else
++      {
++        if (aj.colour != null)
          {
-           currentColour = applyConservation(currentColour, j);
 -          currentColour = shadeCalculation(annotation, j);
++          result = aj.colour;
          }
        }
 -      // if (conservationColouring)
 -      // {
 -      // currentColour = applyConservation(currentColour, j);
 -      // }
      }
-     return currentColour;
 -    // }
 -    return currentColour;
++    else
++    {
++      result = shadeCalculation(ann, j);
++    }
++
++    return result;
    }
  
 -  private Color shadeCalculation(AlignmentAnnotation annotation, int j)
 +  /**
 +   * 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)
    {
 -
 -    // calculate a shade
      float range = 1f;
 -    if (thresholdIsMinMax
 -            && annotation.threshold != null
 +    float value = ann.annotations[col].value;
 +    if (thresholdIsMinMax && ann.threshold != null
              && aboveAnnotationThreshold == ABOVE_THRESHOLD
 -            && annotation.annotations[j].value >= annotation.threshold.value)
 +            && value >= ann.threshold.value)
      {
 -      range = (annotation.annotations[j].value - annotation.threshold.value)
 -              / (annotation.graphMax - annotation.threshold.value);
 +      range = (value - ann.threshold.value)
 +              / (ann.graphMax - ann.threshold.value);
      }
 -    else if (thresholdIsMinMax && annotation.threshold != null
 +    else if (thresholdIsMinMax && ann.threshold != null
              && aboveAnnotationThreshold == BELOW_THRESHOLD
 -            && annotation.annotations[j].value >= annotation.graphMin)
 +            && value <= ann.threshold.value)
      {
 -      range = (annotation.annotations[j].value - annotation.graphMin)
 -              / (annotation.threshold.value - annotation.graphMin);
 +      range = (value - ann.graphMin) / (ann.threshold.value - ann.graphMin);
      }
      else
      {
      seqAssociated = sassoc;
    }
  
 +  public boolean isThresholdIsMinMax()
 +  {
 +    return thresholdIsMinMax;
 +  }
 +
-   public void setThresholdIsMinMax(boolean thresholdIsMinMax)
++  public void setThresholdIsMinMax(boolean minMax)
++  {
++    this.thresholdIsMinMax = minMax;
++  }
++
+   @Override
+   public String getSchemeName()
+   {
+     return "Annotation";
+   }
+   @Override
+   public boolean isSimple()
    {
-     this.thresholdIsMinMax = thresholdIsMinMax;
+     return false;
    }
  }