Merge remote-tracking branch 'origin/develop' into
authorkiramt <k.mourao@dundee.ac.uk>
Fri, 5 May 2017 09:35:48 +0000 (10:35 +0100)
committerkiramt <k.mourao@dundee.ac.uk>
Fri, 5 May 2017 09:35:48 +0000 (10:35 +0100)
features/JAL-2388hiddencolumnschanges

Conflicts:
src/jalview/gui/AnnotationColumnChooser.java
src/jalview/io/AnnotationFile.java

1  2 
src/jalview/appletgui/AlignViewport.java
src/jalview/appletgui/AnnotationColumnChooser.java
src/jalview/datamodel/Alignment.java
src/jalview/datamodel/AlignmentView.java
src/jalview/gui/AlignViewport.java
src/jalview/gui/AnnotationColumnChooser.java
src/jalview/io/AnnotationFile.java
src/jalview/io/JSONFile.java
src/jalview/viewmodel/AlignmentViewport.java
test/jalview/io/AnnotationFileIOTest.java
test/jalview/io/JSONFileTest.java

@@@ -27,7 -27,6 +27,7 @@@ import jalview.bin.JalviewLite
  import jalview.commands.CommandI;
  import jalview.datamodel.AlignmentI;
  import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.SearchResults;
  import jalview.datamodel.SearchResultsI;
  import jalview.datamodel.Sequence;
@@@ -150,6 -149,9 +150,9 @@@ public class AlignViewport extends Alig
        showConsensus = applet.getDefaultParameter("showConsensus",
                showConsensus);
  
+       showOccupancy = applet.getDefaultParameter("showOccupancy",
+               showOccupancy);
        setShowUnconserved(applet.getDefaultParameter("showUnconserved",
                getShowUnconserved()));
  
    {
      getStructureSelectionManager().sendSelection(
              new SequenceGroup(getSelectionGroup()),
 -            new ColumnSelection(getColumnSelection()), this);
 +            new ColumnSelection(getColumnSelection()),
 +            new HiddenColumns(getAlignment().getHiddenColumns()), this);
    }
  
    /**
@@@ -21,7 -21,7 +21,7 @@@
  package jalview.appletgui;
  
  import jalview.datamodel.AlignmentAnnotation;
 -import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.schemes.AnnotationColourGradient;
  import jalview.util.MessageManager;
  import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
@@@ -110,7 -110,7 +110,7 @@@ public class AnnotationColumnChooser ex
  
    private int actionOption = ACTION_OPTION_SELECT;
  
 -  private ColumnSelection oldColumnSelection;
 +  private HiddenColumns oldHiddenColumns;
  
    public AnnotationColumnChooser()
    {
      {
        return;
      }
 -    setOldColumnSelection(av.getColumnSelection());
 +    setOldHiddenColumns(av.getAlignment().getHiddenColumns());
      adjusting = true;
      Vector<String> list = new Vector<String>();
      int index = 1;
      }
  
      populateThresholdComboBox(threshold);
+     AnnotationColumnChooser lastChooser = av
+             .getAnnotationColumnSelectionState();
      // restore Object state from the previous session if one exists
-     if (av.getAnnotationColumnSelectionState() != null)
+     if (lastChooser != null)
      {
-       currentSearchPanel = av.getAnnotationColumnSelectionState()
+       currentSearchPanel = lastChooser
                .getCurrentSearchPanel();
-       currentStructureFilterPanel = av.getAnnotationColumnSelectionState()
+       currentStructureFilterPanel = lastChooser
                .getCurrentStructureFilterPanel();
-       annotations.select(av.getAnnotationColumnSelectionState()
+       annotations.select(lastChooser
                .getAnnotations().getSelectedIndex());
-       threshold.select(av.getAnnotationColumnSelectionState()
+       threshold.select(lastChooser
                .getThreshold().getSelectedIndex());
-       actionOption = av.getAnnotationColumnSelectionState()
+       actionOption = lastChooser
                .getActionOption();
+       percentThreshold.setState(lastChooser.percentThreshold.getState());
      }
  
      try
  
      thresholdValue.setEnabled(false);
      thresholdValue.setColumns(7);
+     thresholdValue.setCaretPosition(0);
  
      ok.addActionListener(this);
      cancel.addActionListener(this);
      // thresholdPanel.setFont(JvSwingUtils.getLabelFont());
      // thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
  
+     percentThreshold.setLabel("As percentage");
+     percentThreshold.addItemListener(this);
      actionPanel.setBackground(Color.white);
      // actionPanel.setFont(JvSwingUtils.getLabelFont());
  
      thresholdPanel.add(getThreshold());
      thresholdPanel.add(slider);
      thresholdPanel.add(thresholdValue);
+     thresholdPanel.add(percentThreshold);
  
      actionPanel.add(ok);
      actionPanel.add(cancel);
    @SuppressWarnings("unchecked")
    public void reset()
    {
 -    if (this.getOldColumnSelection() != null)
 +    if (this.getOldHiddenColumns() != null)
      {
        av.getColumnSelection().clear();
  
        if (av.getAnnotationColumnSelectionState() != null)
        {
 -        ColumnSelection oldSelection = av
 +        HiddenColumns oldHidden = av
                  .getAnnotationColumnSelectionState()
 -                .getOldColumnSelection();
 -        if (oldSelection != null && oldSelection.getHiddenColumns() != null
 -                && !oldSelection.getHiddenColumns().isEmpty())
 +                .getOldHiddenColumns();
 +        if (oldHidden != null && oldHidden.getListOfCols() != null
 +                && !oldHidden.getListOfCols().isEmpty())
          {
 -          for (Iterator<int[]> itr = oldSelection.getHiddenColumns()
 +          for (Iterator<int[]> itr = oldHidden.getListOfCols()
                    .iterator(); itr.hasNext();)
            {
              int positions[] = itr.next();
              av.hideColumns(positions[0], positions[1]);
            }
          }
 -        av.setColumnSelection(oldSelection);
 +        av.getAlignment().setHiddenColumns(oldHidden);
        }
        ap.paintAlignment(true);
      }
    {
      if (!adjusting)
      {
-       thresholdValue.setText((slider.getValue() / 1000f) + "");
+       setThresholdValueText();
        valueChanged(!sliderDragging);
      }
    }
  
      slider.setEnabled(true);
      thresholdValue.setEnabled(true);
+     percentThreshold.setEnabled(true);
  
      if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
      {
        slider.setEnabled(false);
        thresholdValue.setEnabled(false);
        thresholdValue.setText("");
+       percentThreshold.setEnabled(false);
        // build filter params
      }
      else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
        slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
        slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
        slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
-       thresholdValue.setText(getCurrentAnnotation().threshold.value + "");
+       setThresholdValueText();
        // slider.setMajorTickSpacing((int) (range / 10f));
        slider.setEnabled(true);
        thresholdValue.setEnabled(true);
+       percentThreshold.setEnabled(true);
        adjusting = false;
  
        // build filter params
      ap.paintAlignment(true);
    }
  
 -  public ColumnSelection getOldColumnSelection()
 +  public HiddenColumns getOldHiddenColumns()
    {
 -    return oldColumnSelection;
 +    return oldHiddenColumns;
    }
  
 -  public void setOldColumnSelection(ColumnSelection currentColumnSelection)
 +  public void setOldHiddenColumns(HiddenColumns currentHiddenColumns)
    {
 -    if (currentColumnSelection != null)
 +    if (currentHiddenColumns != null)
      {
 -      this.oldColumnSelection = new ColumnSelection(currentColumnSelection);
 +      this.oldHiddenColumns = new HiddenColumns(currentHiddenColumns);
      }
    }
  
      {
        threshold_actionPerformed(null);
      }
+     else if (e.getSource() == percentThreshold)
+     {
+       if (!adjusting)
+       {
+         percentageValue_actionPerformed();
+       }
+     }
    }
  
    public void selectedAnnotationChanged()
    @Override
    public void actionPerformed(ActionEvent evt)
    {
-     if (evt.getSource() == thresholdValue)
-     {
-       try
-       {
-         float f = new Float(thresholdValue.getText()).floatValue();
-         slider.setValue((int) (f * 1000));
-         adjustmentValueChanged(null);
-       } catch (NumberFormatException ex)
-       {
-       }
-     }
  
-     else if (evt.getSource() == ok)
+     if (evt.getSource() == ok)
      {
        ok_actionPerformed(null);
      }
@@@ -62,8 -62,6 +62,8 @@@ public class Alignment implements Align
  
    HiddenSequences hiddenSequences;
  
 +  HiddenColumns hiddenCols;
 +
    public Hashtable alignmentProperties;
  
    private List<AlignedCodonFrame> codonFrameList;
@@@ -72,7 -70,6 +72,7 @@@
    {
      groups = Collections.synchronizedList(new ArrayList<SequenceGroup>());
      hiddenSequences = new HiddenSequences(this);
 +    hiddenCols = new HiddenColumns();
      codonFrameList = new ArrayList<AlignedCodonFrame>();
  
      nucleotide = Comparison.isNucleotide(seqs);
    public Alignment(SeqCigar[] alseqs)
    {
      SequenceI[] seqs = SeqCigar.createAlignmentSequences(alseqs,
 -            gapCharacter, new ColumnSelection(), null);
 +            gapCharacter, new HiddenColumns(), null);
      initAlignment(seqs);
    }
  
    }
  
    @Override
 +  public HiddenColumns getHiddenColumns()
 +  {
 +    return hiddenCols;
 +  }
 +
 +  @Override
    public CigarArray getCompactAlignment()
    {
      synchronized (sequences)
      return aa;
    }
  
-   /**
-    * Returns an iterable collection of any annotations that match on given
-    * sequence ref, calcId and label (ignoring null values).
-    */
    @Override
    public Iterable<AlignmentAnnotation> findAnnotations(SequenceI seq,
            String calcId, String label)
      ArrayList<AlignmentAnnotation> aa = new ArrayList<AlignmentAnnotation>();
      for (AlignmentAnnotation ann : getAlignmentAnnotation())
      {
-       if (ann.getCalcId() != null && ann.getCalcId().equals(calcId)
-               && ann.sequenceRef != null && ann.sequenceRef == seq
-               && ann.label != null && ann.label.equals(label))
+       if ((calcId == null || (ann.getCalcId() != null && ann.getCalcId()
+               .equals(calcId)))
+               && (seq == null || (ann.sequenceRef != null && ann.sequenceRef == seq))
+               && (label == null || (ann.label != null && ann.label
+                       .equals(label))))
        {
          aa.add(ann);
        }
      }
      return new int[] { startPos, endPos };
    }
 +
 +  @Override
 +  public void setHiddenColumns(HiddenColumns cols)
 +  {
 +    hiddenCols = cols;
 +  }
  }
@@@ -141,14 -141,13 +141,14 @@@ public class AlignmentVie
     *          the view
     */
    public AlignmentView(AlignmentI alignment,
 -          ColumnSelection columnSelection, SequenceGroup selection,
 + HiddenColumns hidden,
 +          SequenceGroup selection,
            boolean hasHiddenColumns, boolean selectedRegionOnly,
            boolean recordGroups)
    {
      // refactored from AlignViewport.getAlignmentView(selectedOnly);
      this(new jalview.datamodel.CigarArray(alignment,
 -            (hasHiddenColumns ? columnSelection : null),
 +            (hasHiddenColumns ? hidden : null),
              (selectedRegionOnly ? selection : null)),
              (selectedRegionOnly && selection != null) ? selection
                      .getStartRes() : 0);
     *          char
     * @return Object[] { SequenceI[], ColumnSelection}
     */
 -  public Object[] getAlignmentAndColumnSelection(char gapCharacter)
 +  public Object[] getAlignmentAndHiddenColumns(char gapCharacter)
    {
 -    ColumnSelection colsel = new ColumnSelection();
 +    HiddenColumns hidden = new HiddenColumns();
  
      return new Object[] {
 -        SeqCigar.createAlignmentSequences(sequences, gapCharacter, colsel,
 -                contigs), colsel };
 +        SeqCigar.createAlignmentSequences(sequences, gapCharacter, hidden,
 +                contigs), hidden };
    }
  
    /**
      if (contigs != null && contigs.length > 0)
      {
        SequenceI[] alignment = new SequenceI[sequences.length];
 -      ColumnSelection columnselection = new ColumnSelection();
 +      // ColumnSelection columnselection = new ColumnSelection();
 +      HiddenColumns hidden = new HiddenColumns();
        if (contigs != null && contigs.length > 0)
        {
          int start = 0;
              }
            }
            // mark hidden segment as hidden in the new alignment
 -          columnselection.hideColumns(nwidth, nwidth + contigs[contig + 2]
 +          hidden.hideColumns(nwidth, nwidth + contigs[contig + 2]
                    - 1);
            nwidth += contigs[contig + 2];
          }
            }
          }
        }
 -      return new Object[] { alignment, columnselection };
 +      return new Object[] { alignment, hidden };
      }
      else
      {
        }
        else
        {
 -        return getAlignmentAndColumnSelection(gapCharacter);
 +        return getAlignmentAndHiddenColumns(gapCharacter);
        }
      }
    }
        if (start < fwidth)
        {
          viscontigs[nvis] = start;
-         viscontigs[nvis + 1] = fwidth; // end is inclusive
+         viscontigs[nvis + 1] = fwidth - 1; // end is inclusive
          nvis += 2;
        }
        return viscontigs;
      }
      else
      {
-       return new int[] { 0, width };
+       return new int[] { 0, width - 1 };
      }
    }
  
    }
  
    public static void testSelectionViews(AlignmentI alignment,
 -          ColumnSelection csel, SequenceGroup selection)
 +          HiddenColumns hidden, SequenceGroup selection)
    {
      System.out.println("Testing standard view creation:\n");
      AlignmentView view = null;
      {
        System.out
                .println("View with no hidden columns, no limit to selection, no groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, false, false,
 +      view = new AlignmentView(alignment, hidden, selection, false, false,
                false);
        summariseAlignmentView(view, System.out);
  
      {
        System.out
                .println("View with no hidden columns, no limit to selection, and all groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, false, false,
 +      view = new AlignmentView(alignment, hidden, selection, false, false,
                true);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
        System.out
                .println("View with no hidden columns, limited to selection and no groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, false, true,
 +      view = new AlignmentView(alignment, hidden, selection, false, true,
                false);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
        System.out
                .println("View with no hidden columns, limited to selection, and all groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, false, true,
 +      view = new AlignmentView(alignment, hidden, selection, false, true,
                true);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
        System.out
                .println("View *with* hidden columns, no limit to selection, no groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, true, false,
 +      view = new AlignmentView(alignment, hidden, selection, true, false,
                false);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
        System.out
                .println("View *with* hidden columns, no limit to selection, and all groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, true, false,
 +      view = new AlignmentView(alignment, hidden, selection, true, false,
                true);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
        System.out
                .println("View *with* hidden columns, limited to selection and no groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, true, true,
 +      view = new AlignmentView(alignment, hidden, selection, true, true,
                false);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
        System.out
                .println("View *with* hidden columns, limited to selection, and all groups to be collected:");
 -      view = new AlignmentView(alignment, csel, selection, true, true, true);
 +      view = new AlignmentView(alignment, hidden, selection, true, true,
 +              true);
        summariseAlignmentView(view, System.out);
      } catch (Exception e)
      {
@@@ -35,7 -35,6 +35,7 @@@ import jalview.datamodel.AlignedCodonFr
  import jalview.datamodel.Alignment;
  import jalview.datamodel.AlignmentI;
  import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.PDBEntry;
  import jalview.datamodel.SearchResults;
  import jalview.datamodel.SearchResultsI;
@@@ -148,12 -147,12 +148,12 @@@ public class AlignViewport extends Alig
     * @param hiddenColumns
     *          ColumnSelection
     */
 -  public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns)
 +  public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns)
    {
      setAlignment(al);
      if (hiddenColumns != null)
      {
 -      colSel = hiddenColumns;
 +      al.setHiddenColumns(hiddenColumns);
      }
      init();
    }
     * @param seqsetid
     *          (may be null)
     */
 -  public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
 +  public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns,
            String seqsetid)
    {
      this(al, hiddenColumns, seqsetid, null);
     * @param viewid
     *          (may be null)
     */
 -  public AlignViewport(AlignmentI al, ColumnSelection hiddenColumns,
 +  public AlignViewport(AlignmentI al, HiddenColumns hiddenColumns,
            String seqsetid, String viewid)
    {
      sequenceSetID = seqsetid;
      setAlignment(al);
      if (hiddenColumns != null)
      {
 -      colSel = hiddenColumns;
 +      al.setHiddenColumns(hiddenColumns);
      }
      init();
    }
                false);
        showGroupConsensus = Cache.getDefault("SHOW_GROUP_CONSENSUS", false);
        showConsensus = Cache.getDefault("SHOW_IDENTITY", true);
+       showOccupancy = Cache.getDefault(Preferences.SHOW_OCCUPANCY, true);
      }
      initAutoAnnotation();
      String colourProperty = alignment.isNucleotide() ? Preferences.DEFAULT_COLOUR_NUC
      {
        end = alignment.getWidth();
      }
 -    viscontigs = colSel.getVisibleContigs(start, end);
 +    viscontigs = alignment.getHiddenColumns().getVisibleContigs(start, end);
      return viscontigs;
    }
  
      jalview.structure.StructureSelectionManager
              .getStructureSelectionManager(Desktop.instance).sendSelection(
                      new SequenceGroup(getSelectionGroup()),
 -                    new ColumnSelection(getColumnSelection()), this);
 +                    new ColumnSelection(getColumnSelection()),
 +                    new HiddenColumns(getAlignment().getHiddenColumns()),
 +                    this);
    }
  
    /**
@@@ -22,7 -22,7 +22,7 @@@
  package jalview.gui;
  
  import jalview.datamodel.AlignmentAnnotation;
 -import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.schemes.AnnotationColourGradient;
  import jalview.util.MessageManager;
  import jalview.viewmodel.annotationfilter.AnnotationFilterParameter;
@@@ -86,7 -86,7 +86,7 @@@ public class AnnotationColumnChooser ex
  
    private int actionOption = ACTION_OPTION_SELECT;
  
 -  private ColumnSelection oldColumnSelection;
 +  private HiddenColumns oldHiddenColumns;
  
    public AnnotationColumnChooser(AlignViewport av, final AlignmentPanel ap)
    {
      {
        return;
      }
 -    setOldColumnSelection(av.getColumnSelection());
 +    setOldHiddenColumns(av.getAlignment().getHiddenColumns());
      adjusting = true;
  
      setAnnotations(new JComboBox<String>(getAnnotationItems(false)));
      populateThresholdComboBox(threshold);
+     AnnotationColumnChooser lastChooser = av
+             .getAnnotationColumnSelectionState();
      // restore Object state from the previous session if one exists
-     if (av.getAnnotationColumnSelectionState() != null)
+     if (lastChooser != null)
      {
-       currentSearchPanel = av.getAnnotationColumnSelectionState()
+       currentSearchPanel = lastChooser
                .getCurrentSearchPanel();
-       currentStructureFilterPanel = av.getAnnotationColumnSelectionState()
+       currentStructureFilterPanel = lastChooser
                .getCurrentStructureFilterPanel();
-       annotations.setSelectedIndex(av.getAnnotationColumnSelectionState()
+       annotations.setSelectedIndex(lastChooser
                .getAnnotations().getSelectedIndex());
-       threshold.setSelectedIndex(av.getAnnotationColumnSelectionState()
+       threshold.setSelectedIndex(lastChooser
                .getThreshold().getSelectedIndex());
-       actionOption = av.getAnnotationColumnSelectionState()
+       actionOption = lastChooser
                .getActionOption();
+       percentThreshold.setSelected(lastChooser.percentThreshold
+               .isSelected());
      }
  
      try
      thresholdPanel.setFont(JvSwingUtils.getLabelFont());
      thresholdPanel.setLayout(new MigLayout("", "[left][right]", "[][]"));
  
+     percentThreshold.setBackground(Color.white);
+     percentThreshold.setFont(JvSwingUtils.getLabelFont());
      JPanel actionPanel = new JPanel();
      actionPanel.setBackground(Color.white);
      actionPanel.setFont(JvSwingUtils.getLabelFont());
      ngStructureFilterPanel = new StructureFilterPanel(this);
  
      thresholdPanel.add(getThreshold());
-     thresholdPanel.add(thresholdValue, "wrap");
-     thresholdPanel.add(slider, "grow, span, wrap");
+     thresholdPanel.add(percentThreshold, "wrap");
+     thresholdPanel.add(slider, "grow");
+     thresholdPanel.add(thresholdValue, "span, wrap");
  
      actionPanel.add(ok);
      actionPanel.add(cancel);
    @Override
    protected void reset()
    {
 -    if (this.getOldColumnSelection() != null)
 +    if (this.getOldHiddenColumns() != null)
      {
        av.getColumnSelection().clear();
  
        if (av.getAnnotationColumnSelectionState() != null)
        {
 -        ColumnSelection oldSelection = av
 +        HiddenColumns oldHidden = av
                  .getAnnotationColumnSelectionState()
 -                .getOldColumnSelection();
 -        if (oldSelection != null && oldSelection.getHiddenColumns() != null
 -                && !oldSelection.getHiddenColumns().isEmpty())
 +                .getOldHiddenColumns();
 +        if (oldHidden != null && oldHidden.getListOfCols() != null
 +                && !oldHidden.getListOfCols().isEmpty())
          {
 -          for (Iterator<int[]> itr = oldSelection.getHiddenColumns()
 +          for (Iterator<int[]> itr = oldHidden.getListOfCols()
                    .iterator(); itr.hasNext();)
            {
              int positions[] = itr.next();
              av.hideColumns(positions[0], positions[1]);
            }
          }
 -        av.setColumnSelection(oldSelection);
 +        av.getAlignment().setHiddenColumns(oldHidden);
        }
        ap.paintAlignment(true);
      }
  
      slider.setEnabled(true);
      thresholdValue.setEnabled(true);
+     percentThreshold.setEnabled(true);
  
      if (selectedThresholdItem == AnnotationColourGradient.NO_THRESHOLD)
      {
        slider.setEnabled(false);
        thresholdValue.setEnabled(false);
        thresholdValue.setText("");
+       percentThreshold.setEnabled(false);
        // build filter params
      }
      else if (selectedThresholdItem != AnnotationColourGradient.NO_THRESHOLD)
        slider.setMinimum((int) (getCurrentAnnotation().graphMin * 1000));
        slider.setMaximum((int) (getCurrentAnnotation().graphMax * 1000));
        slider.setValue((int) (getCurrentAnnotation().threshold.value * 1000));
-       thresholdValue.setText(getCurrentAnnotation().threshold.value + "");
+       
+       setThresholdValueText();
        slider.setMajorTickSpacing((int) (range / 10f));
        slider.setEnabled(true);
        thresholdValue.setEnabled(true);
      ap.paintAlignment(true);
    }
  
 -
 -  public ColumnSelection getOldColumnSelection()
 +  public HiddenColumns getOldHiddenColumns()
    {
 -    return oldColumnSelection;
 +    return oldHiddenColumns;
    }
  
 -  public void setOldColumnSelection(ColumnSelection currentColumnSelection)
 +  public void setOldHiddenColumns(HiddenColumns currentHiddenColumns)
    {
 -    if (currentColumnSelection != null)
 +    if (currentHiddenColumns != null)
      {
 -      this.oldColumnSelection = new ColumnSelection(currentColumnSelection);
 +      this.oldHiddenColumns = new HiddenColumns(currentHiddenColumns);
      }
    }
  
@@@ -27,7 -27,6 +27,7 @@@ import jalview.datamodel.AlignmentI
  import jalview.datamodel.Annotation;
  import jalview.datamodel.ColumnSelection;
  import jalview.datamodel.GraphLine;
 +import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.HiddenSequences;
  import jalview.datamodel.SequenceGroup;
  import jalview.datamodel.SequenceI;
@@@ -110,23 -109,24 +110,22 @@@ public class AnnotationFil
     */
    public class ViewDef
    {
-     public String viewname;
+     // TODO this class is not used - remove?
+     public final String viewname;
  
-     public HiddenSequences hidseqs;
+     public final HiddenSequences hidseqs;
  
-     public HiddenColumns hiddencols;
 -    public final ColumnSelection hiddencols;
 -
 -    // public final Vector visibleGroups;
++    public final HiddenColumns hiddencols;
  
-     public Vector visibleGroups;
+     public final Hashtable hiddenRepSeqs;
  
-     public Hashtable hiddenRepSeqs;
-     public ViewDef(String viewname, HiddenSequences hidseqs,
-             HiddenColumns hiddencols, Hashtable hiddenRepSeqs)
+     public ViewDef(String vname, HiddenSequences hseqs,
 -            ColumnSelection hcols, Hashtable hRepSeqs)
++            HiddenColumns hcols, Hashtable hRepSeqs)
      {
-       this.viewname = viewname;
-       this.hidseqs = hidseqs;
-       this.hiddencols = hiddencols;
-       this.hiddenRepSeqs = hiddenRepSeqs;
+       this.viewname = vname;
+       this.hidseqs = hseqs;
+       this.hiddencols = hcols;
+       this.hiddenRepSeqs = hRepSeqs;
      }
    }
  
     */
    public String printAnnotations(AlignmentAnnotation[] annotations,
            List<SequenceGroup> list, Hashtable properties,
 -          ColumnSelection cs, AlignmentI al, ViewDef view)
 + HiddenColumns cs,
 +          AlignmentI al, ViewDef view)
    {
      if (view != null)
      {
        }
        if (list == null)
        {
-         list = view.visibleGroups;
+         // list = view.visibleGroups;
        }
        if (cs == null)
        {
      if (cs != null && cs.hasHiddenColumns())
      {
        text.append("VIEW_HIDECOLS\t");
 -      List<int[]> hc = cs.getHiddenColumns();
 +      List<int[]> hc = cs.getListOfCols();
        boolean comma = false;
        for (int[] r : hc)
        {
      return false;
    }
  
-   public void printGroups(List<SequenceGroup> list)
+   protected void printGroups(List<SequenceGroup> list)
    {
      SequenceI seqrep = null;
      for (SequenceGroup sg : list)
        if (sg.cs != null)
        {
          text.append("colour=");
-         text.append(sg.cs.toString());
+         text.append(ColourSchemeProperty.getColourName(sg.cs
+                 .getColourScheme()));
          text.append("\t");
          if (sg.cs.getThreshold() != 0)
          {
            String file, DataSourceType protocol)
    {
      ColumnSelection colSel = viewport.getColumnSelection();
 +    HiddenColumns hidden = viewport.getAlignment().getHiddenColumns();
      if (colSel == null)
      {
        colSel = new ColumnSelection();
      }
 -    boolean rslt = readAnnotationFile(viewport.getAlignment(), colSel,
 +    if (hidden == null)
 +    {
 +      hidden = new HiddenColumns();
 +    }
 +    boolean rslt = readAnnotationFile(viewport.getAlignment(), hidden,
              file, protocol);
 -    if (rslt && (colSel.hasSelectedColumns() || colSel.hasHiddenColumns()))
 +    if (rslt && (colSel.hasSelectedColumns() || hidden.hasHiddenColumns()))
      {
        viewport.setColumnSelection(colSel);
 +      viewport.getAlignment().setHiddenColumns(hidden);
      }
  
      return rslt;
      return readAnnotationFile(al, null, file, sourceType);
    }
  
 -  public boolean readAnnotationFile(AlignmentI al, ColumnSelection colSel,
 +  public boolean readAnnotationFile(AlignmentI al, HiddenColumns hidden,
            String file, DataSourceType sourceType)
    {
      BufferedReader in = null;
        }
        if (in != null)
        {
 -        return parseAnnotationFrom(al, colSel, in);
 +        return parseAnnotationFrom(al, hidden, in);
        }
  
      } catch (Exception ex)
  
    private static String GRAPHLINE = "GRAPHLINE", COMBINE = "COMBINE";
  
 -  public boolean parseAnnotationFrom(AlignmentI al, ColumnSelection colSel,
 +  public boolean parseAnnotationFrom(AlignmentI al, HiddenColumns hidden,
            BufferedReader in) throws Exception
    {
      nlinesread = 0;
          {
            if (st.hasMoreTokens())
            {
 -            if (colSel == null)
 +            if (hidden == null)
              {
 -              colSel = new ColumnSelection();
 +              hidden = new HiddenColumns();
              }
 -            parseHideCols(colSel, st.nextToken());
 +            parseHideCols(hidden, st.nextToken());
            }
            modified = true;
            continue;
            }
            if (sr != null)
            {
 -            if (colSel == null)
 +            if (hidden == null)
              {
                System.err
                        .println("Cannot process HIDE_INSERTIONS without an alignment view: Ignoring line: "
              else
              {
                // consider deferring this till after the file has been parsed ?
 -              colSel.hideInsertionsFor(sr);
 +              hidden.hideInsertionsFor(sr);
              }
            }
            modified = true;
      return modified;
    }
  
 -  private void parseHideCols(ColumnSelection colSel, String nextToken)
 +  private void parseHideCols(HiddenColumns hidden, String nextToken)
    {
      StringTokenizer inval = new StringTokenizer(nextToken, ",");
      while (inval.hasMoreTokens())
          from = to = Integer.parseInt(range);
          if (from >= 0)
          {
 -          colSel.hideColumns(from, to);
 +          hidden.hideColumns(from, to);
          }
        }
        else
          }
          if (from > 0 && to >= from)
          {
 -          colSel.hideColumns(from, to);
 +          hidden.hideColumns(from, to);
          }
        }
      }
      return printAnnotations(viewport.isShowAnnotation() ? viewport
              .getAlignment().getAlignmentAnnotation() : null, viewport
              .getAlignment().getGroups(), viewport.getAlignment()
 -            .getProperties(), viewport.getColumnSelection(),
 +            .getProperties(), viewport.getAlignment().getHiddenColumns(),
              viewport.getAlignment(), null);
    }
  
@@@ -32,7 -32,7 +32,7 @@@ import jalview.bin.BuildDetails
  import jalview.datamodel.AlignmentAnnotation;
  import jalview.datamodel.AlignmentI;
  import jalview.datamodel.Annotation;
 -import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.HiddenSequences;
  import jalview.datamodel.Sequence;
  import jalview.datamodel.SequenceFeature;
@@@ -47,6 -47,7 +47,7 @@@ import jalview.json.binding.biojson.v1.
  import jalview.json.binding.biojson.v1.SequenceGrpPojo;
  import jalview.json.binding.biojson.v1.SequencePojo;
  import jalview.renderer.seqfeatures.FeatureColourFinder;
+ import jalview.schemes.ColourSchemeProperty;
  import jalview.schemes.JalviewColourScheme;
  import jalview.schemes.ResidueColourScheme;
  import jalview.util.ColorUtils;
@@@ -83,7 -84,9 +84,7 @@@ public class JSONFile extends AlignFil
  
    private FeatureRenderer fr;
  
 -  private List<int[]> hiddenColumns;
 -
 -  private ColumnSelection columnSelection;
 +  private HiddenColumns hiddenColumns;
  
    private List<String> hiddenSeqRefs;
  
          {
            SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
            seqGrpPojo.setGroupName(seqGrp.getName());
-           seqGrpPojo.setColourScheme(seqGrp.getColourScheme()
-                   .getSchemeName());
+           seqGrpPojo.setColourScheme(ColourSchemeProperty
+                   .getColourName(seqGrp.getColourScheme()));
            seqGrpPojo.setColourText(seqGrp.getColourText());
            seqGrpPojo.setDescription(seqGrp.getDescription());
            seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
      // hidden column business
      if (getViewport().hasHiddenColumns())
      {
 -      List<int[]> hiddenCols = getViewport().getColumnSelection()
 -              .getHiddenColumns();
 +      List<int[]> hiddenCols = getViewport().getAlignment()
 +              .getHiddenColumns()
 +              .getListOfCols();
        StringBuilder hiddenColsBuilder = new StringBuilder();
        for (int[] range : hiddenCols)
        {
      String hiddenCols = (String) jvSettingsJson.get("hiddenCols");
      if (hiddenCols != null && !hiddenCols.isEmpty())
      {
 -      columnSelection = new ColumnSelection();
 +      hiddenColumns = new HiddenColumns();
        String[] rangeStrings = hiddenCols.split(";");
        for (String rangeString : rangeStrings)
        {
          String[] range = rangeString.split("-");
 -        columnSelection.hideColumns(Integer.valueOf(range[0]),
 +        hiddenColumns.hideColumns(Integer.valueOf(range[0]),
                  Integer.valueOf(range[1]));
        }
      }
          }
        }
      }
-     globalColourScheme = (viewport.getGlobalColourScheme() == null) ? ResidueColourScheme.NONE
-             : viewport.getGlobalColourScheme().getSchemeName();
+     globalColourScheme = ColourSchemeProperty.getColourName(viewport
+             .getGlobalColourScheme());
      setDisplayedFeatures(viewport.getFeaturesDisplayed());
      showSeqFeatures = viewport.isShowSequenceFeatures();
  
      return annotations;
    }
  
 -  public List<int[]> getHiddenColumns()
 -  {
 -    return hiddenColumns;
 -  }
 -
    @Override
 -  public ColumnSelection getColumnSelection()
 +  public HiddenColumns getHiddenColumns()
    {
 -    return columnSelection;
 +    return hiddenColumns;
    }
  
 -  public void setColumnSelection(ColumnSelection columnSelection)
 +  public void setHiddenColumns(HiddenColumns hidden)
    {
 -    this.columnSelection = columnSelection;
 +    this.hiddenColumns = hidden;
    }
  
    @Override
   */
  package jalview.viewmodel;
  
 -import java.awt.Color;
 -import java.beans.PropertyChangeSupport;
 -import java.util.ArrayDeque;
 -import java.util.ArrayList;
 -import java.util.BitSet;
 -import java.util.Deque;
 -import java.util.HashMap;
 -import java.util.Hashtable;
 -import java.util.List;
 -import java.util.Map;
 -
  import jalview.analysis.AnnotationSorter.SequenceAnnotationOrder;
  import jalview.analysis.Conservation;
  import jalview.api.AlignCalcManagerI;
@@@ -35,7 -46,6 +35,7 @@@ import jalview.datamodel.AlignmentView
  import jalview.datamodel.Annotation;
  import jalview.datamodel.CigarArray;
  import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.HiddenSequences;
  import jalview.datamodel.ProfilesI;
  import jalview.datamodel.SearchResultsI;
@@@ -52,23 -62,13 +52,24 @@@ import jalview.structure.VamsasSource
  import jalview.util.Comparison;
  import jalview.util.MapList;
  import jalview.util.MappingUtils;
+ import jalview.util.MessageManager;
  import jalview.viewmodel.styles.ViewStyle;
  import jalview.workers.AlignCalcManager;
  import jalview.workers.ComplementConsensusThread;
  import jalview.workers.ConsensusThread;
  import jalview.workers.StrucConsensusThread;
  
 +import java.awt.Color;
 +import java.beans.PropertyChangeSupport;
 +import java.util.ArrayDeque;
 +import java.util.ArrayList;
 +import java.util.BitSet;
 +import java.util.Deque;
 +import java.util.HashMap;
 +import java.util.Hashtable;
 +import java.util.List;
 +import java.util.Map;
 +
  /**
   * base class holding visualization and analysis attributes and common logic for
   * an active alignment view displayed in the GUI
@@@ -824,7 -824,7 +825,7 @@@ public abstract class AlignmentViewpor
    public void updateConsensus(final AlignmentViewPanel ap)
    {
      // see note in mantis : issue number 8585
-     if ((consensus == null || gapcounts == null) || !autoCalculateConsensus)
+     if (consensus == null || !autoCalculateConsensus)
      {
        return;
      }
      }
    }
  
 -  public void setHiddenColumns(ColumnSelection colsel)
 +  public void setHiddenColumns(HiddenColumns hidden)
    {
 -    this.colSel = colsel;
 +    this.alignment.setHiddenColumns(hidden);
 +    // this.colSel = colsel;
    }
  
    @Override
    @Override
    public boolean hasHiddenColumns()
    {
 -    return colSel != null && colSel.hasHiddenColumns();
 +    return colSel != null
 +            && alignment.getHiddenColumns().hasHiddenColumns();
    }
  
    public void updateHiddenColumns()
  
    protected boolean showConsensus = true;
  
+   protected boolean showOccupancy = true;
    private Map<SequenceI, Color> sequenceColours = new HashMap<SequenceI, Color>();
  
    protected SequenceAnnotationOrder sortAnnotationsBy = null;
        return;
      }
  
 -    colSel.hideSelectedColumns();
 +    colSel.hideSelectedColumns(alignment);
      setSelectionGroup(null);
      isColSelChanged(true);
    }
    {
      if (start == end)
      {
 -      colSel.hideColumns(start);
 +      colSel.hideSelectedColumns(start, alignment.getHiddenColumns());
      }
      else
      {
 -      colSel.hideColumns(start, end);
 +      alignment.getHiddenColumns().hideColumns(start, end);
      }
      isColSelChanged(true);
    }
  
    public void showColumn(int col)
    {
 -    colSel.revealHiddenColumns(col);
 +    alignment.getHiddenColumns().revealHiddenColumns(col, colSel);
      isColSelChanged(true);
    }
  
    public void showAllHiddenColumns()
    {
 -    colSel.revealAllHiddenColumns();
 +    alignment.getHiddenColumns().revealAllHiddenColumns(colSel);
      isColSelChanged(true);
    }
  
    @Override
    public void invertColumnSelection()
    {
 -    colSel.invertColumnSelection(0, alignment.getWidth());
 +    colSel.invertColumnSelection(0, alignment.getWidth(), alignment);
    }
  
    @Override
    @Override
    public CigarArray getViewAsCigars(boolean selectedRegionOnly)
    {
 -    return new CigarArray(alignment, colSel,
 +    return new CigarArray(alignment, alignment.getHiddenColumns(),
              (selectedRegionOnly ? selectionGroup : null));
    }
  
    public jalview.datamodel.AlignmentView getAlignmentView(
            boolean selectedOnly, boolean markGroups)
    {
 -    return new AlignmentView(alignment, colSel, selectionGroup,
 -            colSel != null && colSel.hasHiddenColumns(), selectedOnly,
 +    return new AlignmentView(alignment, alignment.getHiddenColumns(),
 +            selectionGroup, alignment.getHiddenColumns() != null
 +                    && alignment.getHiddenColumns().hasHiddenColumns(),
 +            selectedOnly,
              markGroups);
    }
  
      }
  
      selection = new String[iSize];
 -    if (colSel != null && colSel.hasHiddenColumns())
 +    if (alignment.getHiddenColumns() != null
 +            && alignment.getHiddenColumns().hasHiddenColumns())
      {
 -      selection = colSel.getVisibleSequenceStrings(start, end, seqs);
 +      selection = alignment.getHiddenColumns().getVisibleSequenceStrings(
 +              start, end, seqs);
      }
      else
      {
  
      do
      {
 -      if (colSel != null && colSel.hasHiddenColumns())
 +      HiddenColumns hidden = alignment.getHiddenColumns();
 +      if (hidden != null && hidden.hasHiddenColumns())
        {
          if (start == 0)
          {
 -          start = colSel.adjustForHiddenColumns(start);
 +          start = hidden.adjustForHiddenColumns(start);
          }
  
 -        end = colSel.getHiddenBoundaryRight(start);
 +        end = hidden.getHiddenBoundaryRight(start);
          if (start == end)
          {
            end = max;
  
        regions.add(new int[] { start, end });
  
 -      if (colSel != null && colSel.hasHiddenColumns())
 +      if (hidden != null && hidden.hasHiddenColumns())
        {
 -        start = colSel.adjustForHiddenColumns(end);
 -        start = colSel.getHiddenBoundaryLeft(start) + 1;
 +        start = hidden.adjustForHiddenColumns(end);
 +        start = hidden.getHiddenBoundaryLeft(start) + 1;
        }
      } while (end < max);
  
          AlignmentAnnotation clone = new AlignmentAnnotation(annot);
          if (selectedOnly && selectionGroup != null)
          {
 -          colSel.makeVisibleAnnotation(selectionGroup.getStartRes(),
 +          alignment.getHiddenColumns().makeVisibleAnnotation(
 +                  selectionGroup.getStartRes(),
                    selectionGroup.getEndRes(), clone);
          }
          else
          {
 -          colSel.makeVisibleAnnotation(clone);
 +          alignment.getHiddenColumns().makeVisibleAnnotation(clone);
          }
          ala.add(clone);
        }
        {
          initRNAStructure();
        }
-       consensus = new AlignmentAnnotation("Consensus", "PID",
+       consensus = new AlignmentAnnotation("Consensus",
+               MessageManager.getString("label.consensus_descr"),
                new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
        initConsensus(consensus);
-       gapcounts = new AlignmentAnnotation("Occupancy",
-               "Number of aligned positions",
-               new Annotation[1], 0f, alignment.getHeight(),
-               AlignmentAnnotation.BAR_GRAPH);
-       initGapCounts(gapcounts);
+       initGapCounts();
  
        initComplementConsensus();
      }
          if (doConsensus)
          {
            complementConsensus = new AlignmentAnnotation("cDNA Consensus",
-                   "PID for cDNA", new Annotation[1], 0f, 100f,
+                   MessageManager
+                           .getString("label.complement_consensus_descr"),
+                   new Annotation[1], 0f, 100f,
                    AlignmentAnnotation.BAR_GRAPH);
            initConsensus(complementConsensus);
            return true;
  
    // these should be extracted from the view model - style and settings for
    // derived annotation
-   private void initGapCounts(AlignmentAnnotation counts)
+   private void initGapCounts()
    {
-     counts.hasText = false;
-     counts.autoCalculated = true;
-     counts.graph = AlignmentAnnotation.BAR_GRAPH;
-     if (showConsensus)
+     if (showOccupancy)
      {
-       alignment.addAnnotation(counts);
+       gapcounts = new AlignmentAnnotation("Occupancy",
+               MessageManager.getString("label.occupancy_descr"),
+               new Annotation[1], 0f,
+               alignment.getHeight(), AlignmentAnnotation.BAR_GRAPH);
+       gapcounts.hasText = true;
+       gapcounts.autoCalculated = true;
+       gapcounts.scaleColLabel = true;
+       gapcounts.graph = AlignmentAnnotation.BAR_GRAPH;
+       alignment.addAnnotation(gapcounts);
      }
    }
  
        if (conservation == null)
        {
          conservation = new AlignmentAnnotation("Conservation",
-                 "Conservation of total alignment less than "
-                         + getConsPercGaps() + "% gaps", new Annotation[1],
+                 MessageManager.formatMessage("label.conservation_descr",
+                         getConsPercGaps()), new Annotation[1],
                  0f, 11f, AlignmentAnnotation.BAR_GRAPH);
          conservation.hasText = true;
          conservation.autoCalculated = true;
        if (quality == null)
        {
          quality = new AlignmentAnnotation("Quality",
-                 "Alignment Quality based on Blosum62 scores",
+                 MessageManager.getString("label.quality_descr"),
                  new Annotation[1], 0f, 11f, AlignmentAnnotation.BAR_GRAPH);
          quality.hasText = true;
          quality.autoCalculated = true;
    {
      if (alignment.hasRNAStructure() && strucConsensus == null)
      {
-       strucConsensus = new AlignmentAnnotation("StrucConsensus", "PID",
+       strucConsensus = new AlignmentAnnotation("StrucConsensus",
+               MessageManager.getString("label.strucconsensus_descr"),
                new Annotation[1], 0f, 100f, AlignmentAnnotation.BAR_GRAPH);
        strucConsensus.hasText = true;
        strucConsensus.autoCalculated = true;
@@@ -24,7 -24,7 +24,7 @@@ import static org.testng.AssertJUnit.as
  import static org.testng.AssertJUnit.assertTrue;
  
  import jalview.datamodel.AlignmentI;
 -import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.gui.JvOptionPane;
  import jalview.io.AnnotationFile.ViewDef;
  
@@@ -115,7 -115,7 +115,7 @@@ public class AnnotationFileIOTes
      try
      {
        AlignmentI al = readAlignmentFile(f);
 -      ColumnSelection cs = new ColumnSelection();
 +      HiddenColumns cs = new HiddenColumns();
        assertTrue(
                "Test "
                        + testname
                        DataSourceType.FILE));
  
        AnnotationFile aff = new AnnotationFile();
+       // ViewDef is not used by Jalview
        ViewDef v = aff.new ViewDef(null, al.getHiddenSequences(), cs,
                new Hashtable());
        String anfileout = new AnnotationFile().printAnnotations(
@@@ -27,7 -27,7 +27,7 @@@ import jalview.datamodel.Alignment
  import jalview.datamodel.AlignmentAnnotation;
  import jalview.datamodel.AlignmentI;
  import jalview.datamodel.Annotation;
 -import jalview.datamodel.ColumnSelection;
 +import jalview.datamodel.HiddenColumns;
  import jalview.datamodel.Sequence;
  import jalview.datamodel.SequenceFeature;
  import jalview.datamodel.SequenceGroup;
@@@ -79,7 -79,7 +79,7 @@@ public class JSONFileTes
  
    private HashMap<String, SequenceGroup> expectedGrps = new HashMap<String, SequenceGroup>();
  
 -  private ColumnSelection expectedColSel = new ColumnSelection();
 +  private HiddenColumns expectedColSel = new HiddenColumns();
  
    private SequenceI[] expectedHiddenSeqs = new SequenceI[1];
  
        expectedSeqs.put(seq.getName(), seq);
      }
  
-     // create and add sequence groups
-     ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
+     // create and add a sequence group
+     List<SequenceI> grpSeqs = new ArrayList<SequenceI>();
      grpSeqs.add(seqs[1]);
      grpSeqs.add(seqs[2]);
      grpSeqs.add(seqs[3]);
      grpSeqs.add(seqs[4]);
-     SequenceGroup seqGrp = new SequenceGroup(grpSeqs, "JGroup:1883305585",
+     SequenceGroup seqGrp = new SequenceGroup(grpSeqs,
+             "JGroup:1883305585",
              null, true, true, false, 21, 29);
      ColourSchemeI scheme = ColourSchemeMapper.getJalviewColourScheme(
              "zappo", seqGrp);
      TEST_SEQ_HEIGHT = expectedSeqs.size();
      TEST_GRP_HEIGHT = expectedGrps.size();
      TEST_ANOT_HEIGHT = expectedAnnots.size();
 -    TEST_CS_HEIGHT = expectedColSel.getHiddenColumns().size();
 +    TEST_CS_HEIGHT = expectedColSel.getListOfCols().size();
  
      exportSettings = new AlignExportSettingI()
      {
        jf = (JSONFile) formatAdapter.getAlignFile();
  
        AlignFrame af = new AlignFrame(alignment, jf.getHiddenSequences(),
 -              jf.getColumnSelection(), AlignFrame.DEFAULT_WIDTH,
 +              jf.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
                AlignFrame.DEFAULT_HEIGHT);
        af.getViewport().setShowSequenceFeatures(jf.isShowSeqFeatures());
        String colourSchemeName = jf.getGlobalColourScheme();
    @Test(groups = { "Functional" })
    public void hiddenColsTest()
    {
 -    ColumnSelection cs = testJsonFile.getColumnSelection();
 +    HiddenColumns cs = testJsonFile.getHiddenColumns();
      Assert.assertNotNull(cs);
 -    Assert.assertNotNull(cs.getHiddenColumns());
 -    List<int[]> hiddenCols = cs.getHiddenColumns();
 +    Assert.assertNotNull(cs.getListOfCols());
 +    List<int[]> hiddenCols = cs.getListOfCols();
      Assert.assertEquals(hiddenCols.size(), TEST_CS_HEIGHT);
      Assert.assertEquals(hiddenCols.get(0), expectedColSel
 -            .getHiddenColumns().get(0),
 +            .getListOfCols().get(0),
              "Mismatched hidden columns!");
    }
  
              "Zappo colour scheme expected!");
    }
  
-   @Test(groups = { "Functional" })
    /**
-    * Test for bug JAL-2489, NPE when exporting BioJSON with global colour scheme set as 'None'
+    * Test for bug JAL-2489, NPE when exporting BioJSON with global colour
+    * scheme, and a group colour scheme, set as 'None'
     */
-   public void testBioJSONRoundTripWithGlobalColourSchemeSetAsNone()
+   @Test(groups = { "Functional" })
+   public void testBioJSONRoundTripWithColourSchemeNone()
    {
      AppletFormatAdapter formatAdapter = new AppletFormatAdapter();
  
        JSONFile bioJsonFile = (JSONFile) formatAdapter.getAlignFile();
        AlignFrame alignFrame = new AlignFrame(_alignment,
                bioJsonFile.getHiddenSequences(),
 -              bioJsonFile.getColumnSelection(), AlignFrame.DEFAULT_WIDTH,
 +              bioJsonFile.getHiddenColumns(), AlignFrame.DEFAULT_WIDTH,
                AlignFrame.DEFAULT_HEIGHT);
-       // Change colour scheme to 'None' and perform round trip
+       /*
+        * Create a group on the alignment;
+        * Change global and group colour scheme to 'None' and perform round trip
+        */
+       SequenceGroup sg = new SequenceGroup();
+       sg.addSequence(_alignment.getSequenceAt(0), false);
+       sg.setColourScheme(null);
        ColourSchemeI cs = ColourSchemeMapper.getJalviewColourScheme(
                ResidueColourScheme.NONE, _alignment);
        alignFrame.changeColour(cs);
      // System.out.println(">>>>>>>>>>>>>> features matched : " + matched);
      return matched;
    }
+   /**
+    * Test group roundtrip with null (None) group colour scheme
+    * 
+    * @throws IOException
+    */
+   @Test(groups = { "Functional" })
+   public void testGrpParsed_colourNone() throws IOException
+   {
+     AlignmentI copy = new Alignment(testAlignment);
+     SequenceGroup sg = testAlignment.getGroups().get(0);
+     SequenceGroup copySg = new SequenceGroup(new ArrayList<SequenceI>(),
+             sg.getName(),
+             null, sg.getDisplayBoxes(), sg.getDisplayText(),
+             sg.getColourText(), sg.getStartRes(), sg.getEndRes());
+     for (SequenceI seq : sg.getSequences())
+     {
+       int seqIndex = testAlignment.findIndex(seq);
+       copySg.addSequence(copy.getSequenceAt(seqIndex), false);
+     }
+     copy.addGroup(copySg);
+     AlignFrame af = new AlignFrame(copy, copy.getWidth(), copy.getHeight());
+     AppletFormatAdapter formatAdapter = new AppletFormatAdapter(
+             af.alignPanel);
+     String jsonOutput = formatAdapter.formatSequences(FileFormat.Json,
+             copy, false);
+     formatAdapter = new AppletFormatAdapter();
+     AlignmentI newAlignment = formatAdapter.readFile(jsonOutput,
+             DataSourceType.PASTE, FileFormat.Json);
+     Assert.assertNotNull(newAlignment.getGroups());
+     for (SequenceGroup seqGrp : newAlignment.getGroups())
+     {
+       SequenceGroup expectedGrp = expectedGrps.get(seqGrp.getName());
+       AssertJUnit.assertTrue(
+               "Failed SequenceGroup Test for >>> " + seqGrp.getName(),
+               isGroupMatched(expectedGrp, seqGrp));
+       passedCount++;
+     }
+     AssertJUnit.assertEquals("Some SequenceGroups did not pass the test",
+             TEST_GRP_HEIGHT, passedCount);
+   }
  }