JAL-1894 update year/version in copyright
[jalview.git] / src / jalview / io / JSONFile.java
index 26ffb7c..9402562 100644 (file)
@@ -1,27 +1,57 @@
+/*
+ * Jalview - A Sequence Alignment Editor and Viewer (Version 2.9.0b1)
+ * Copyright (C) 2015 The Jalview Authors
+ * 
+ * This file is part of Jalview.
+ * 
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License 
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *  
+ * Jalview is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty 
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR 
+ * PURPOSE.  See the GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview.  If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
+
 package jalview.io;
 
+import jalview.api.AlignExportSettingI;
+import jalview.api.AlignViewportI;
+import jalview.api.AlignmentViewPanel;
+import jalview.api.ComplexAlignFile;
+import jalview.api.FeatureRenderer;
 import jalview.api.FeaturesDisplayedI;
+import jalview.bin.BuildDetails;
 import jalview.datamodel.AlignmentAnnotation;
+import jalview.datamodel.AlignmentI;
 import jalview.datamodel.Annotation;
+import jalview.datamodel.ColumnSelection;
+import jalview.datamodel.HiddenSequences;
 import jalview.datamodel.Sequence;
 import jalview.datamodel.SequenceFeature;
 import jalview.datamodel.SequenceGroup;
 import jalview.datamodel.SequenceI;
-import jalview.gui.AlignFrame;
-import jalview.gui.Desktop;
-import jalview.json.binding.v1.AlignmentAnnotationPojo;
-import jalview.json.binding.v1.AlignmentPojo;
-import jalview.json.binding.v1.AnnotationPojo;
-import jalview.json.binding.v1.JalviewSettingsPojo;
-import jalview.json.binding.v1.JalviewSettingsPojo.JalviewBioJsColorSchemeMapper;
-import jalview.json.binding.v1.SequenceFeaturesPojo;
-import jalview.json.binding.v1.SequenceGrpPojo;
-import jalview.json.binding.v1.SequencePojo;
-import jalview.schemes.ColourSchemeI;
+import jalview.json.binding.biojson.v1.AlignmentAnnotationPojo;
+import jalview.json.binding.biojson.v1.AlignmentPojo;
+import jalview.json.binding.biojson.v1.AnnotationDisplaySettingPojo;
+import jalview.json.binding.biojson.v1.AnnotationPojo;
+import jalview.json.binding.biojson.v1.ColourSchemeMapper;
+import jalview.json.binding.biojson.v1.SequenceFeaturesPojo;
+import jalview.json.binding.biojson.v1.SequenceGrpPojo;
+import jalview.json.binding.biojson.v1.SequencePojo;
 import jalview.schemes.ColourSchemeProperty;
-import jalview.viewmodel.AlignmentViewport;
+import jalview.schemes.UserColourScheme;
+import jalview.viewmodel.seqfeatures.FeaturesDisplayed;
 
+import java.awt.Color;
 import java.io.IOException;
+import java.io.Reader;
 import java.util.ArrayList;
 import java.util.Hashtable;
 import java.util.Iterator;
@@ -32,21 +62,19 @@ import org.json.simple.JSONArray;
 import org.json.simple.JSONObject;
 import org.json.simple.parser.JSONParser;
 
-public class JSONFile extends AlignFile
+public class JSONFile extends AlignFile implements ComplexAlignFile
 {
-  private static ColourSchemeI colourScheme;
-
-  private static boolean seqFeaturesEnabled;
+  private static String version = new BuildDetails().getVersion();
 
-  private String jalviewVersion;
+  private String webstartUrl = "http://www.jalview.org/services/launchApp";
 
-  private String webStartLaunchServletUrl = "http://www.jalview.org/services/launchApp";
+  private String application = "Jalview";
 
   public static final String FILE_EXT = "json";
 
   public static final String FILE_DESC = "JSON";
 
-  private String globalColorScheme;
+  private String globalColourScheme;
 
   private boolean showSeqFeatures;
 
@@ -54,9 +82,17 @@ public class JSONFile extends AlignFile
 
   private FeaturesDisplayedI displayedFeatures;
 
-  private AlignmentViewport av;
+  private FeatureRenderer fr;
+
+  private List<int[]> hiddenColumns;
+
+  private ColumnSelection columnSelection;
+
+  private List<String> hiddenSeqRefs;
 
-  private jalview.api.FeatureRenderer fr;
+  private ArrayList<SequenceI> hiddenSequences;
+
+  private final static String TCOFFEE_SCORE = "TCoffeeScore";
 
   public JSONFile()
   {
@@ -76,39 +112,61 @@ public class JSONFile extends AlignFile
   @Override
   public void parse() throws IOException
   {
-    StringBuilder jsonStringBuilder = new StringBuilder();
-    String currentLine;
-    while ((currentLine = nextLine()) != null)
-    {
-      jsonStringBuilder.append(currentLine);
-    }
-    parse(jsonStringBuilder.toString());
+    parse(getReader());
 
   }
 
   @Override
   public String print()
   {
+    String jsonOutput = null;
     try
     {
-      JSONExportSettings exportSettings = new JSONExportSettings();
-      exportSettings.setExportAnnotations(true);
-      exportSettings.setExportGroups(true);
-      exportSettings.setExportJalviewSettings(true);
-      exportSettings.setExportSequenceFeatures(true);
-
       AlignmentPojo jsonAlignmentPojo = new AlignmentPojo();
-      if (Desktop.getCurrentAlignFrame() != null)
+      AlignExportSettingI exportSettings = getExportSettings();
+
+      // if no export settings were supplied use the following with all values
+      // defaulting to true
+      if (exportSettings == null)
       {
-        globalColorScheme = ColourSchemeProperty.getColourName(Desktop
-                .getCurrentAlignFrame().getViewport()
-                .getGlobalColourScheme());
-        this.av = Desktop.getCurrentAlignFrame().getCurrentView();
-        this.fr = Desktop.getCurrentAlignFrame().alignPanel
-                .cloneFeatureRenderer();
-        displayedFeatures = av.getFeaturesDisplayed();
-        showSeqFeatures = Desktop.getCurrentAlignFrame().showSeqFeatures
-                .isSelected();
+        exportSettings = new AlignExportSettingI()
+        {
+          @Override
+          public boolean isExportHiddenSequences()
+          {
+            return true;
+          }
+
+          @Override
+          public boolean isExportHiddenColumns()
+          {
+            return true;
+          }
+
+          @Override
+          public boolean isExportGroups()
+          {
+            return true;
+          }
+
+          @Override
+          public boolean isExportFeatures()
+          {
+            return true;
+          }
+
+          @Override
+          public boolean isExportAnnotations()
+          {
+            return true;
+          }
+
+          @Override
+          public boolean isCancelled()
+          {
+            return false;
+          }
+        };
       }
 
       int count = 0;
@@ -118,7 +176,7 @@ public class JSONFile extends AlignFile
         name.append(seq.getName()).append("/").append(seq.getStart())
                 .append("-").append(seq.getEnd());
         SequencePojo jsonSeqPojo = new SequencePojo();
-        jsonSeqPojo.setId(seq.getName() + "_" + seq.hashCode());
+        jsonSeqPojo.setId(String.valueOf(seq.hashCode()));
         jsonSeqPojo.setOrder(++count);
         jsonSeqPojo.setEnd(seq.getEnd());
         jsonSeqPojo.setStart(seq.getStart());
@@ -126,15 +184,28 @@ public class JSONFile extends AlignFile
         jsonSeqPojo.setSeq(seq.getSequenceAsString());
         jsonAlignmentPojo.getSeqs().add(jsonSeqPojo);
       }
-
-      if (exportSettings.isExportJalviewSettings())
+      jsonAlignmentPojo.setGlobalColorScheme(globalColourScheme);
+      jsonAlignmentPojo.getAppSettings().put("application", application);
+      jsonAlignmentPojo.getAppSettings().put("version", version);
+      jsonAlignmentPojo.getAppSettings().put("webStartUrl", webstartUrl);
+      jsonAlignmentPojo.getAppSettings().put("showSeqFeatures",
+              String.valueOf(showSeqFeatures));
+
+      String[] hiddenSections = getHiddenSections();
+      if (hiddenSections != null)
       {
-        JalviewSettingsPojo jvSettings = new JalviewSettingsPojo();
-        jvSettings.setGlobalColorScheme(globalColorScheme);
-        jvSettings.setJalviewVersion(jalviewVersion);
-        jvSettings.setWebStartUrl(webStartLaunchServletUrl);
-        jvSettings.setShowSeqFeatures(showSeqFeatures);
-        jsonAlignmentPojo.setJalviewSettings(jvSettings);
+        if (hiddenSections[0] != null
+                && exportSettings.isExportHiddenColumns())
+        {
+          jsonAlignmentPojo.getAppSettings().put("hiddenCols",
+                  String.valueOf(hiddenSections[0]));
+        }
+        if (hiddenSections[1] != null
+                && exportSettings.isExportHiddenSequences())
+        {
+          jsonAlignmentPojo.getAppSettings().put("hiddenSeqs",
+                  String.valueOf(hiddenSections[1]));
+        }
       }
 
       if (exportSettings.isExportAnnotations())
@@ -142,16 +213,26 @@ public class JSONFile extends AlignFile
         jsonAlignmentPojo
                 .setAlignAnnotation(annotationToJsonPojo(annotations));
       }
+      else
+      {
+        // These color schemes require annotation, disable them if annotations
+        // are not exported
+        if (globalColourScheme.equalsIgnoreCase("RNA Helices")
+                || globalColourScheme.equalsIgnoreCase("T-COFFEE SCORES"))
+        {
+          jsonAlignmentPojo.setGlobalColorScheme("None");
+        }
+      }
 
-      if (exportSettings.isExportSequenceFeatures())
+      if (exportSettings.isExportFeatures())
       {
-        jsonAlignmentPojo.setSeqFeatures(sequenceFeatureToJsonPojo(seqs,
-                displayedFeatures));
+        jsonAlignmentPojo
+                .setSeqFeatures(sequenceFeatureToJsonPojo(seqs, fr));
       }
 
-      if (exportSettings.isExportGroups() && seqGroups.size() > 0)
+      if (exportSettings.isExportGroups() && seqGroups != null
+              && seqGroups.size() > 0)
       {
-        ArrayList<SequenceGrpPojo> sequenceGroupsPojo = new ArrayList<SequenceGrpPojo>();
         for (SequenceGroup seqGrp : seqGroups)
         {
           SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
@@ -167,43 +248,103 @@ public class JSONFile extends AlignFile
           seqGrpPojo.setShowNonconserved(seqGrp.getShowNonconserved());
           for (SequenceI seq : seqGrp.getSequences())
           {
-            seqGrpPojo.getSeqsHash().add(
-                    seq.getName() + "_" + seq.hashCode());
+            seqGrpPojo.getSequenceRefs()
+                    .add(String.valueOf(seq.hashCode()));
           }
           jsonAlignmentPojo.getSeqGroups().add(seqGrpPojo);
         }
       }
-      com.json.JSONObject generatedJSon = new com.json.JSONObject(
+      org.json.JSONObject generatedJSon = new org.json.JSONObject(
               jsonAlignmentPojo);
-      String jsonOutput = generatedJSon.toString();
+      jsonOutput = generatedJSon.toString();
       return jsonOutput.replaceAll("xstart", "xStart").replaceAll("xend",
               "xEnd");
     } catch (Exception e)
     {
       e.printStackTrace();
-      throw e;
     }
+    return jsonOutput;
+  }
+
+  public String[] getHiddenSections()
+  {
+    String[] hiddenSections = new String[2];
+    if (getViewport() == null)
+    {
+      return null;
+    }
+
+    // hidden column business
+    if (getViewport().hasHiddenColumns())
+    {
+      List<int[]> hiddenCols = getViewport().getColumnSelection()
+              .getHiddenColumns();
+      StringBuilder hiddenColsBuilder = new StringBuilder();
+      for (int[] range : hiddenCols)
+      {
+        hiddenColsBuilder.append(";").append(range[0]).append("-")
+                .append(range[1]);
+      }
+
+      hiddenColsBuilder.deleteCharAt(0);
+      hiddenSections[0] = hiddenColsBuilder.toString();
+    }
+
+    // hidden rows/seqs business
+    HiddenSequences hiddenSeqsObj = getViewport().getAlignment()
+            .getHiddenSequences();
+    if (hiddenSeqsObj == null || hiddenSeqsObj.hiddenSequences == null)
+    {
+      return hiddenSections;
+    }
+
+    SequenceI[] hiddenSeqs = hiddenSeqsObj.hiddenSequences;
+    StringBuilder hiddenSeqsBuilder = new StringBuilder();
+    for (SequenceI hiddenSeq : hiddenSeqs)
+    {
+      if (hiddenSeq != null)
+      {
+        hiddenSeqsBuilder.append(";").append(hiddenSeq.hashCode());
+      }
+    }
+    if (hiddenSeqsBuilder.length() > 0)
+    {
+      hiddenSeqsBuilder.deleteCharAt(0);
+    }
+    hiddenSections[1] = hiddenSeqsBuilder.toString();
+
+    return hiddenSections;
   }
 
-  public static List<SequenceFeaturesPojo> sequenceFeatureToJsonPojo(
-          List<SequenceI> seqs, FeaturesDisplayedI displayedFeatures)
+  public List<SequenceFeaturesPojo> sequenceFeatureToJsonPojo(
+          List<SequenceI> seqs, FeatureRenderer fr)
   {
+    displayedFeatures = (fr == null) ? null : fr.getFeaturesDisplayed();
     List<SequenceFeaturesPojo> sequenceFeaturesPojo = new ArrayList<SequenceFeaturesPojo>();
     for (SequenceI seq : seqs)
     {
       SequenceI dataSetSequence = seq.getDatasetSequence();
       SequenceFeature[] seqFeatures = (dataSetSequence == null) ? null
               : seq.getDatasetSequence().getSequenceFeatures();
+
+      seqFeatures = (seqFeatures == null) ? seq.getSequenceFeatures()
+              : seqFeatures;
+      if (seqFeatures == null)
+      {
+        continue;
+      }
+
       for (SequenceFeature sf : seqFeatures)
       {
         if (displayedFeatures != null
                 && displayedFeatures.isVisible(sf.getType()))
         {
-          // String fillColor = ((fr != null) ? jalview.util.Format
-          // .getHexString(fr.findFeatureColour(Color.white, seq,
-          // seq.findIndex(sf.getBegin()))) : null);
           SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo(
-                  seq.getName() + "_" + seq.hashCode());
+                  String.valueOf(seq.hashCode()));
+
+          String featureColour = (fr == null) ? null : jalview.util.Format
+                  .getHexString(fr.findFeatureColour(Color.white, seq,
+                          seq.findIndex(sf.getBegin())));
           jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
           jsonFeature.setXend(seq.findIndex(sf.getEnd()));
           jsonFeature.setType(sf.getType());
@@ -211,7 +352,7 @@ public class JSONFile extends AlignFile
           jsonFeature.setLinks(sf.links);
           jsonFeature.setOtherDetails(sf.otherDetails);
           jsonFeature.setScore(sf.getScore());
-          // jsonFeature.setFillColor(fillColor);
+          jsonFeature.setFillColor(featureColour);
           jsonFeature.setFeatureGroup(sf.getFeatureGroup());
           sequenceFeaturesPojo.add(jsonFeature);
         }
@@ -224,11 +365,35 @@ public class JSONFile extends AlignFile
           Vector<AlignmentAnnotation> annotations)
   {
     List<AlignmentAnnotationPojo> jsonAnnotations = new ArrayList<AlignmentAnnotationPojo>();
+    if (annotations == null)
+    {
+      return jsonAnnotations;
+    }
     for (AlignmentAnnotation annot : annotations)
     {
       AlignmentAnnotationPojo alignAnnotPojo = new AlignmentAnnotationPojo();
       alignAnnotPojo.setDescription(annot.description);
       alignAnnotPojo.setLabel(annot.label);
+      if (!Double.isNaN(annot.score))
+      {
+        alignAnnotPojo.setScore(annot.score);
+      }
+      alignAnnotPojo.setCalcId(annot.getCalcId());
+      alignAnnotPojo.setGraphType(annot.graph);
+
+      AnnotationDisplaySettingPojo annotSetting = new AnnotationDisplaySettingPojo();
+      annotSetting.setBelowAlignment(annot.belowAlignment);
+      annotSetting.setCentreColLabels(annot.centreColLabels);
+      annotSetting.setScaleColLabel(annot.scaleColLabel);
+      annotSetting.setShowAllColLabels(annot.showAllColLabels);
+      annotSetting.setVisible(annot.visible);
+      annotSetting.setHasIcon(annot.hasIcons);
+      alignAnnotPojo.setAnnotationSettings(annotSetting);
+      SequenceI refSeq = annot.sequenceRef;
+      if (refSeq != null)
+      {
+        alignAnnotPojo.setSequenceRef(String.valueOf(refSeq.hashCode()));
+      }
       for (Annotation annotation : annot.annotations)
       {
         AnnotationPojo annotationPojo = new AnnotationPojo();
@@ -238,12 +403,28 @@ public class JSONFile extends AlignFile
           annotationPojo.setValue(annotation.value);
           annotationPojo
                   .setSecondaryStructure(annotation.secondaryStructure);
-          annotationPojo.setDisplayCharacter(annotation.displayCharacter);
+          String displayChar = annotation.displayCharacter == null ? null
+                  : annotation.displayCharacter;
+          // System.out.println("--------------------->[" + displayChar + "]");
+          annotationPojo.setDisplayCharacter(displayChar);
+          if (annotation.colour != null)
+          {
+            annotationPojo.setColour(jalview.util.Format
+                    .getHexString(annotation.colour));
+          }
           alignAnnotPojo.getAnnotations().add(annotationPojo);
         }
         else
         {
-          alignAnnotPojo.getAnnotations().add(annotationPojo);
+          if (annot.getCalcId() != null
+                  && annot.getCalcId().equalsIgnoreCase(TCOFFEE_SCORE))
+          {
+            // do nothing
+          }
+          else
+          {
+            alignAnnotPojo.getAnnotations().add(annotationPojo);
+          }
         }
       }
       jsonAnnotations.add(alignAnnotPojo);
@@ -251,7 +432,8 @@ public class JSONFile extends AlignFile
     return jsonAnnotations;
   }
 
-  public void parse(String jsonAlignmentString)
+  @SuppressWarnings("unchecked")
+  public JSONFile parse(Reader jsonAlignmentString)
   {
     try
     {
@@ -266,21 +448,21 @@ public class JSONFile extends AlignFile
       JSONArray seqGrpJsonArray = (JSONArray) alignmentJsonObj
               .get("seqGroups");
       JSONObject jvSettingsJsonObj = (JSONObject) alignmentJsonObj
-              .get("jalviewSettings");
+              .get("appSettings");
 
       if (jvSettingsJsonObj != null)
       {
-        String jsColourScheme = (String) jvSettingsJsonObj
+        globalColourScheme = (String) jvSettingsJsonObj
                 .get("globalColorScheme");
         Boolean showFeatures = Boolean.valueOf(jvSettingsJsonObj.get(
                 "showSeqFeatures").toString());
-        setColourScheme(getJalviewColorScheme(jsColourScheme));
-        JSONFile.setSeqFeaturesEnabled(showFeatures);
-        // Desktop.setCurrentSeqFeaturesVisible(showFeatures);
+        setShowSeqFeatures(showFeatures);
+        parseHiddenSeqRefsAsList(jvSettingsJsonObj);
+        parseHiddenCols(jvSettingsJsonObj);
       }
 
+      hiddenSequences = new ArrayList<SequenceI>();
       seqMap = new Hashtable<String, Sequence>();
-      // Desktop.setCurrentGlobalColourScheme(cs);
       for (Iterator<JSONObject> sequenceIter = seqJsonArray.iterator(); sequenceIter
               .hasNext();)
       {
@@ -292,9 +474,14 @@ public class JSONFile extends AlignFile
         int end = Integer.valueOf(sequence.get("end").toString());
         Sequence seq = new Sequence(sequenceName, sequcenceString, start,
                 end);
+        if (hiddenSeqRefs != null && hiddenSeqRefs.contains(seqUniqueId))
+        {
+          hiddenSequences.add(seq);
+        }
         seqs.add(seq);
         seqMap.put(seqUniqueId, seq);
       }
+
       parseFeatures(jsonSeqArray);
 
       for (Iterator<JSONObject> seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter
@@ -316,12 +503,12 @@ public class JSONFile extends AlignFile
         int startRes = Integer
                 .valueOf(seqGrpObj.get("startRes").toString());
         int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString());
-        JSONArray seqsHashArray = (JSONArray) seqGrpObj.get("seqsHash");
+        JSONArray sequenceRefs = (JSONArray) seqGrpObj.get("sequenceRefs");
 
         ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
-        if (seqsHashArray.size() > 0)
+        if (sequenceRefs.size() > 0)
         {
-          Iterator<String> seqHashIter = seqsHashArray.iterator();
+          Iterator<String> seqHashIter = sequenceRefs.iterator();
           while (seqHashIter.hasNext())
           {
             String seqHash = seqHashIter.next();
@@ -332,9 +519,10 @@ public class JSONFile extends AlignFile
             }
           }
         }
-        ColourSchemeI scheme = getJalviewColorScheme(colourScheme);
-        SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, scheme,
+        SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, null,
                 displayBoxes, displayText, colourText, startRes, endRes);
+        seqGrp.cs = ColourSchemeMapper.getJalviewColourScheme(colourScheme,
+                seqGrp);
         seqGrp.setShowNonconserved(showNonconserved);
         seqGrp.setDescription(description);
         this.seqGroups.add(seqGrp);
@@ -362,12 +550,20 @@ public class JSONFile extends AlignFile
                     .valueOf(annot.get("value").toString());
             String desc = annot.get("description") == null ? null : annot
                     .get("description").toString();
-
-            char ss = annot.get("secondaryStructure") == null ? null
-                    : annot.get("secondaryStructure").toString().charAt(0);
-            String displayChar = annot.get("displayCharacter").toString();
+            char ss = annot.get("secondaryStructure") == null
+                    || annot.get("secondaryStructure").toString()
+                            .equalsIgnoreCase("u0000") ? ' ' : annot
+                    .get("secondaryStructure").toString().charAt(0);
+            String displayChar = annot.get("displayCharacter") == null ? ""
+                    : annot.get("displayCharacter").toString();
 
             annotations[count] = new Annotation(displayChar, desc, ss, val);
+            if (annot.get("colour") != null)
+            {
+              Color color = UserColourScheme.getColourFromString(annot.get(
+                      "colour").toString());
+              annotations[count].colour = color;
+            }
           }
           ++count;
         }
@@ -375,36 +571,119 @@ public class JSONFile extends AlignFile
         AlignmentAnnotation alignAnnot = new AlignmentAnnotation(alAnnot
                 .get("label").toString(), alAnnot.get("description")
                 .toString(), annotations);
+        alignAnnot.graph = (alAnnot.get("graphType") == null) ? 0 : Integer
+                .valueOf(alAnnot.get("graphType").toString());
+
+        JSONObject diplaySettings = (JSONObject) alAnnot
+                .get("annotationSettings");
+        if (diplaySettings != null)
+        {
+
+          alignAnnot.scaleColLabel = (diplaySettings.get("scaleColLabel") == null) ? false
+                  : Boolean.valueOf(diplaySettings.get("scaleColLabel")
+                          .toString());
+          alignAnnot.showAllColLabels = (diplaySettings
+                  .get("showAllColLabels") == null) ? true : Boolean
+                  .valueOf(diplaySettings.get("showAllColLabels")
+                          .toString());
+          alignAnnot.centreColLabels = (diplaySettings
+                  .get("centreColLabels") == null) ? true
+                  : Boolean.valueOf(diplaySettings.get("centreColLabels")
+                          .toString());
+          alignAnnot.belowAlignment = (diplaySettings.get("belowAlignment") == null) ? false
+                  : Boolean.valueOf(diplaySettings.get("belowAlignment")
+                          .toString());
+          alignAnnot.visible = (diplaySettings.get("visible") == null) ? true
+                  : Boolean.valueOf(diplaySettings.get("visible")
+                          .toString());
+          alignAnnot.hasIcons = (diplaySettings.get("hasIcon") == null) ? true
+                  : Boolean.valueOf(diplaySettings.get("hasIcon")
+                          .toString());
+
+        }
+        if (alAnnot.get("score") != null)
+        {
+          alignAnnot.score = Double
+                  .valueOf(alAnnot.get("score").toString());
+        }
+
+        String calcId = (alAnnot.get("calcId") == null) ? "" : alAnnot.get(
+                "calcId").toString();
+        alignAnnot.setCalcId(calcId);
+        String seqHash = (alAnnot.get("sequenceRef") != null) ? alAnnot
+                .get("sequenceRef").toString() : null;
+
+        Sequence sequence = (seqHash != null) ? seqMap.get(seqHash) : null;
+        if (sequence != null)
+        {
+          alignAnnot.sequenceRef = sequence;
+          sequence.addAlignmentAnnotation(alignAnnot);
+          if (alignAnnot.label.equalsIgnoreCase("T-COFFEE"))
+          {
+            alignAnnot.createSequenceMapping(sequence, sequence.getStart(),
+                    false);
+            sequence.addAlignmentAnnotation(alignAnnot);
+            alignAnnot.adjustForAlignment();
+          }
+        }
+        alignAnnot.validateRangeAndDisplay();
         this.annotations.add(alignAnnot);
-      }
 
+      }
     } catch (Exception e)
     {
       e.printStackTrace();
     }
+    return this;
+  }
+
+  public void parseHiddenSeqRefsAsList(JSONObject jvSettingsJson)
+  {
+    hiddenSeqRefs = new ArrayList<String>();
+    String hiddenSeqs = (String) jvSettingsJson.get("hiddenSeqs");
+    if (hiddenSeqs != null && !hiddenSeqs.isEmpty())
+    {
+      String[] seqRefs = hiddenSeqs.split(";");
+      for (String seqRef : seqRefs)
+      {
+        hiddenSeqRefs.add(seqRef);
+      }
+    }
   }
 
+  public void parseHiddenCols(JSONObject jvSettingsJson)
+  {
+    String hiddenCols = (String) jvSettingsJson.get("hiddenCols");
+    if (hiddenCols != null && !hiddenCols.isEmpty())
+    {
+      columnSelection = new ColumnSelection();
+      String[] rangeStrings = hiddenCols.split(";");
+      for (String rangeString : rangeStrings)
+      {
+        String[] range = rangeString.split("-");
+        columnSelection.hideColumns(Integer.valueOf(range[0]),
+                Integer.valueOf(range[1]));
+      }
+    }
+  }
 
+  @SuppressWarnings("unchecked")
   private void parseFeatures(JSONArray jsonSeqFeatures)
   {
     if (jsonSeqFeatures != null)
     {
-      for (@SuppressWarnings("unchecked")
-      Iterator<JSONObject> seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr
+      displayedFeatures = new FeaturesDisplayed();
+      for (Iterator<JSONObject> seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr
               .hasNext();)
       {
         JSONObject jsonFeature = seqFeatureItr.next();
         Long begin = (Long) jsonFeature.get("xStart");
         Long end = (Long) jsonFeature.get("xEnd");
         String type = (String) jsonFeature.get("type");
-        String color = (String) jsonFeature.get("fillColor");
         String featureGrp = (String) jsonFeature.get("featureGroup");
         String descripiton = (String) jsonFeature.get("description");
         String seqRef = (String) jsonFeature.get("sequenceRef");
         Float score = Float.valueOf(jsonFeature.get("score").toString());
-        // Hashtable otherDetails = (Hashtable) jsonFeature
-        // .get("otherDetails");
-        // sequenceFeature.otherDetails = otherDetails;
 
         Sequence seq = seqMap.get(seqRef);
         SequenceFeature sequenceFeature = new SequenceFeature();
@@ -425,60 +704,102 @@ public class JSONFile extends AlignFile
         sequenceFeature.setBegin(seq.findPosition(begin.intValue()));
         sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1);
         seq.addSequenceFeature(sequenceFeature);
+        displayedFeatures.setVisible(type);
       }
     }
   }
 
-  private ColourSchemeI getJalviewColorScheme(String bioJsColourSchemeName)
+  public String getGlobalColourScheme()
+  {
+    return globalColourScheme;
+  }
+
+  public void setGlobalColorScheme(String globalColourScheme)
+  {
+    this.globalColourScheme = globalColourScheme;
+  }
+
+  @Override
+  public FeaturesDisplayedI getDisplayedFeatures()
   {
-    ColourSchemeI jalviewColor = null;
-    for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper
-            .values())
+    return displayedFeatures;
+  }
+
+  public void setDisplayedFeatures(FeaturesDisplayedI displayedFeatures)
+  {
+    this.displayedFeatures = displayedFeatures;
+  }
+
+  public void configureForView(AlignmentViewPanel avpanel)
+  {
+    super.configureForView(avpanel);
+    AlignViewportI viewport = avpanel.getAlignViewport();
+    AlignmentI alignment = viewport.getAlignment();
+    AlignmentAnnotation[] annots = alignment.getAlignmentAnnotation();
+
+    seqGroups = alignment.getGroups();
+    fr = avpanel.cloneFeatureRenderer();
+
+    // Add non auto calculated annotation to AlignFile
+    for (AlignmentAnnotation annot : annots)
     {
-      if (cs.getBioJsName().equalsIgnoreCase(bioJsColourSchemeName))
+      if (annot != null && !annot.autoCalculated)
       {
-        jalviewColor = cs.getJvColourScheme();
-        break;
+        annotations.add(annot);
       }
     }
-    return jalviewColor;
+    globalColourScheme = ColourSchemeProperty.getColourName(viewport
+            .getGlobalColourScheme());
+    setDisplayedFeatures(viewport.getFeaturesDisplayed());
+    showSeqFeatures = viewport.isShowSequenceFeatures();
+
+  }
+
+  public boolean isShowSeqFeatures()
+  {
+    return showSeqFeatures;
   }
 
-  public void LoadAlignmentFeatures(AlignFrame af)
+  public void setShowSeqFeatures(boolean showSeqFeatures)
   {
-    af.setShowSeqFeatures(JSONFile.isSeqFeaturesEnabled());
-    af.changeColour(getColourScheme());
-    af.setMenusForViewport();
+    this.showSeqFeatures = showSeqFeatures;
   }
 
-  public String getGlobalColorScheme()
+  public Vector<AlignmentAnnotation> getAnnotations()
   {
-    return globalColorScheme;
+    return annotations;
   }
 
-  public void setGlobalColorScheme(String globalColorScheme)
+  public List<int[]> getHiddenColumns()
   {
-    this.globalColorScheme = globalColorScheme;
+    return hiddenColumns;
   }
 
-  public static ColourSchemeI getColourScheme()
+  public ColumnSelection getColumnSelection()
   {
-    return colourScheme;
+    return columnSelection;
   }
 
-  public static void setColourScheme(ColourSchemeI colourScheme)
+  public void setColumnSelection(ColumnSelection columnSelection)
   {
-    JSONFile.colourScheme = colourScheme;
+    this.columnSelection = columnSelection;
   }
 
-  public static boolean isSeqFeaturesEnabled()
+  public SequenceI[] getHiddenSequences()
   {
-    return seqFeaturesEnabled;
+    if (hiddenSequences == null || hiddenSequences.isEmpty())
+    {
+      return new SequenceI[] {};
+    }
+    synchronized (hiddenSequences)
+    {
+      return hiddenSequences.toArray(new SequenceI[hiddenSequences.size()]);
+    }
   }
 
-  public static void setSeqFeaturesEnabled(boolean seqFeaturesEnabled)
+  public void setHiddenSequences(ArrayList<SequenceI> hiddenSequences)
   {
-    JSONFile.seqFeaturesEnabled = seqFeaturesEnabled;
+    this.hiddenSequences = hiddenSequences;
   }
 
   public class JSONExportSettings