From d5858833aeeb20eb747fc02070fee2e530cb592d Mon Sep 17 00:00:00 2001 From: Charles Ofoegbu Date: Thu, 5 Feb 2015 12:41:04 +0000 Subject: [PATCH] JAL-1641 JSONFile format support for jalview alignment --- src/jalview/io/AppletFormatAdapter.java | 37 ++-- src/jalview/io/BioJsHTMLOutput.java | 14 +- src/jalview/io/HtmlFile.java | 2 +- src/jalview/io/IdentifyFile.java | 5 + src/jalview/io/JSONFile.java | 194 ++++++++++++++++++++ ...{BioJsAlignmentPojo.java => AlignmentPojo.java} | 10 +- .../v1/{BioJsFeaturePojo.java => FeaturePojo.java} | 4 +- .../v1/{BioJsSeqPojo.java => SequencePojo.java} | 12 +- 8 files changed, 239 insertions(+), 39 deletions(-) create mode 100644 src/jalview/io/JSONFile.java rename src/jalview/json/binding/v1/{BioJsAlignmentPojo.java => AlignmentPojo.java} (94%) rename src/jalview/json/binding/v1/{BioJsFeaturePojo.java => FeaturePojo.java} (91%) rename src/jalview/json/binding/v1/{BioJsSeqPojo.java => SequencePojo.java} (74%) diff --git a/src/jalview/io/AppletFormatAdapter.java b/src/jalview/io/AppletFormatAdapter.java index 89adead..bbd32be 100755 --- a/src/jalview/io/AppletFormatAdapter.java +++ b/src/jalview/io/AppletFormatAdapter.java @@ -47,7 +47,7 @@ public class AppletFormatAdapter */ public static final String[] READABLE_FORMATS = new String[] { "BLC", "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "STH", - "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC, "HTML" }; // , + "PDB", "JnetFile", "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, "HTML" }; // , // "SimpleBLAST" // }; @@ -57,7 +57,7 @@ public class AppletFormatAdapter */ public static final String[] WRITEABLE_FORMATS = new String[] { "BLC", "CLUSTAL", "FASTA", "MSF", "PileUp", "PIR", "PFAM", "AMSA", - "STH", PhylipFile.FILE_DESC }; + "STH", PhylipFile.FILE_DESC, JSONFile.FILE_DESC }; /** * List of extensions corresponding to file format types in WRITABLE_FNAMES @@ -65,7 +65,7 @@ public class AppletFormatAdapter */ public static final String[] WRITABLE_EXTENSIONS = new String[] { "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa", - "sto,stk", PhylipFile.FILE_EXT, "jvp" }; + "sto,stk", PhylipFile.FILE_EXT, JSONFile.FILE_DESC, "jvp" }; /** * List of writable formats by the application. Order must correspond with the @@ -73,7 +73,7 @@ public class AppletFormatAdapter */ public static final String[] WRITABLE_FNAMES = new String[] { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "STH", - PhylipFile.FILE_DESC, "Jalview" }; + PhylipFile.FILE_DESC, JSONFile.FILE_DESC, "Jalview" }; /** * List of readable format file extensions by application in order @@ -81,7 +81,7 @@ public class AppletFormatAdapter */ public static final String[] READABLE_EXTENSIONS = new String[] { "fa, fasta, mfa, fastq", "aln", "pfam", "msf", "pir", "blc", "amsa", - "jar,jvp", "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT, + "jar,jvp", "sto,stk", "xml,rnaml", PhylipFile.FILE_EXT, JSONFile.FILE_EXT, "html" }; // ".blast" /** @@ -90,7 +90,8 @@ public class AppletFormatAdapter */ public static final String[] READABLE_FNAMES = new String[] { "Fasta", "Clustal", "PFAM", "MSF", "PIR", "BLC", "AMSA", "Jalview", - "Stockholm", "RNAML", PhylipFile.FILE_DESC, "HTML" };// , + "Stockholm", "RNAML", PhylipFile.FILE_DESC, JSONFile.FILE_DESC, + "HTML" };// , // "SimpleBLAST" // }; @@ -271,10 +272,10 @@ public class AppletFormatAdapter { afile = new PhylipFile(inFile, type); } - // else if (format.equals(HtmlFile.FILE_DESC)) - // { - // afile = new HtmlFile(inFile, type); - // } + else if (format.equals(JSONFile.FILE_DESC)) + { + afile = new JSONFile(inFile, type); + } else if (format.equals("RNAML")) { afile = new RnamlFile(inFile, type); @@ -399,10 +400,10 @@ public class AppletFormatAdapter { afile = new PhylipFile(source); } - // else if (format.equals(HtmlFile.FILE_DESC)) - // { - // afile = new HtmlFile(source); - // } + else if (format.equals(JSONFile.FILE_DESC)) + { + afile = new JSONFile(source); + } Alignment al = new Alignment(afile.getSeqsAsArray()); afile.addAnnotations(al); @@ -538,10 +539,10 @@ public class AppletFormatAdapter { afile = new PhylipFile(); } - // else if (format.equalsIgnoreCase(HtmlFile.FILE_DESC)) - // { - // afile = new HtmlFile(); - // } + else if (format.equalsIgnoreCase(JSONFile.FILE_DESC)) + { + afile = new JSONFile(); + } else if (format.equalsIgnoreCase("RNAML")) { afile = new RnamlFile(); diff --git a/src/jalview/io/BioJsHTMLOutput.java b/src/jalview/io/BioJsHTMLOutput.java index db43a3f..12ec4a4 100644 --- a/src/jalview/io/BioJsHTMLOutput.java +++ b/src/jalview/io/BioJsHTMLOutput.java @@ -8,9 +8,9 @@ import jalview.exceptions.NoFileSelectedException; import jalview.gui.AlignViewport; import jalview.gui.AlignmentPanel; import jalview.gui.FeatureRenderer; -import jalview.json.binding.v1.BioJsAlignmentPojo; -import jalview.json.binding.v1.BioJsFeaturePojo; -import jalview.json.binding.v1.BioJsSeqPojo; +import jalview.json.binding.v1.AlignmentPojo; +import jalview.json.binding.v1.FeaturePojo; +import jalview.json.binding.v1.SequencePojo; import jalview.schemes.ColourSchemeProperty; import jalview.util.MessageManager; @@ -117,7 +117,7 @@ public class BioJsHTMLOutput public String getJalviewAlignmentAsJsonString(AlignmentI alignment) throws IOException, JSONException { - BioJsAlignmentPojo bjsAlignment = new BioJsAlignmentPojo(); + AlignmentPojo bjsAlignment = new AlignmentPojo(); bjsAlignment.setGlobalColorScheme(getGlobalColorScheme()); bjsAlignment.setJalviewVersion(jalviewVersion); @@ -130,7 +130,7 @@ public class BioJsHTMLOutput name.append(seq.getName()).append("/").append(seq.getStart()) .append("-").append(seq.getEnd()); - BioJsSeqPojo seqPojo = new BioJsSeqPojo(); + SequencePojo seqPojo = new SequencePojo(); seqPojo.setId(String.valueOf(++count)); seqPojo.setEnd(seq.getEnd()); seqPojo.setStart(seq.getStart()); @@ -141,7 +141,7 @@ public class BioJsHTMLOutput .getSequenceFeatures(); if (seqFeatures != null) { - ArrayList bjsSeqFeatures = new ArrayList(); + ArrayList bjsSeqFeatures = new ArrayList(); for (SequenceFeature sf : seqFeatures) { if (displayedFeatures != null @@ -152,7 +152,7 @@ public class BioJsHTMLOutput String featureColour = jalview.util.Format.getHexString(fr .findFeatureColour(Color.white, seq, seq.findIndex(sf.getBegin()))); - BioJsFeaturePojo bjsFeature = new BioJsFeaturePojo(); + FeaturePojo bjsFeature = new FeaturePojo(); bjsFeature.setFillColor(featureColour); bjsFeature.setXstart(seq.findIndex(sf.getBegin()) - 1); bjsFeature.setXend(seq.findIndex(sf.getEnd())); diff --git a/src/jalview/io/HtmlFile.java b/src/jalview/io/HtmlFile.java index 3cb7c3f..4add5be 100644 --- a/src/jalview/io/HtmlFile.java +++ b/src/jalview/io/HtmlFile.java @@ -3,7 +3,7 @@ package jalview.io; import jalview.datamodel.Sequence; import jalview.datamodel.SequenceFeature; import jalview.gui.AlignFrame; -import jalview.json.binding.v1.BioJsAlignmentPojo.JalviewBioJsColorSchemeMapper; +import jalview.json.binding.v1.AlignmentPojo.JalviewBioJsColorSchemeMapper; import jalview.schemes.ColourSchemeI; import java.io.IOException; diff --git a/src/jalview/io/IdentifyFile.java b/src/jalview/io/IdentifyFile.java index 4fb2516..3b4fd1a 100755 --- a/src/jalview/io/IdentifyFile.java +++ b/src/jalview/io/IdentifyFile.java @@ -136,6 +136,11 @@ public class IdentifyFile break; } + if (data.indexOf("{\"SEQS\":[{\"FEATURES") > -1) + { + reply = JSONFile.FILE_DESC; + break; + } // if (data.matches("<(\"[^\"]*\"|'[^']*'|[^'\">])*>")) if (data.matches("<(?i)html(\"[^\"]*\"|'[^']*'|[^'\">])*>")) { diff --git a/src/jalview/io/JSONFile.java b/src/jalview/io/JSONFile.java new file mode 100644 index 0000000..8a30cf4 --- /dev/null +++ b/src/jalview/io/JSONFile.java @@ -0,0 +1,194 @@ +package jalview.io; + +import jalview.datamodel.AlignmentI; +import jalview.datamodel.Sequence; +import jalview.datamodel.SequenceFeature; +import jalview.datamodel.SequenceI; +import jalview.json.binding.v1.AlignmentPojo; +import jalview.json.binding.v1.AlignmentPojo.JalviewBioJsColorSchemeMapper; +import jalview.json.binding.v1.SequencePojo; +import jalview.schemes.ColourSchemeI; + +import java.io.IOException; +import java.util.Iterator; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.json.simple.parser.JSONParser; + +public class JSONFile extends AlignFile +{ + private ColourSchemeI cs; + + private String jalviewVersion; + + private String webStartLaunchServletUrl = "http://www.jalview.org/services/launchApp"; + + public static final String FILE_EXT = "json"; + + public static final String FILE_DESC = "JSON"; + + private String globalColorScheme; + + private AlignmentI al; + + private jalview.api.FeatureRenderer fr; + + public JSONFile(AlignmentI al) + { + super(); + } + + public JSONFile() + { + super(); + } + + public JSONFile(FileParse source) throws IOException + { + super(source); + } + + public JSONFile(String inFile, String type) throws IOException + { + super(inFile, type); + } + + @Override + public void parse() throws IOException + { + StringBuilder jsonStringBuilder = new StringBuilder(); + String currentLine; + while ((currentLine = nextLine()) != null) + { + jsonStringBuilder.append(currentLine); + } + parse(jsonStringBuilder.toString()); + + } + + @Override + public String print() + { + AlignmentPojo jsonAlignmentPojo = new AlignmentPojo(); + // jsonAlignmentPojo.setGlobalColorScheme(ColourSchemeProperty + // .getColourName(af.getViewport().getGlobalColourScheme())); + jsonAlignmentPojo.setJalviewVersion(jalviewVersion); + jsonAlignmentPojo.setWebStartUrl(webStartLaunchServletUrl); + + int count = 0; + for (SequenceI seq : seqs) + { + StringBuilder name = new StringBuilder(); + name.append(seq.getName()).append("/").append(seq.getStart()) + .append("-").append(seq.getEnd()); + + SequencePojo jsonSeqPojo = new SequencePojo(); + jsonSeqPojo.setId(String.valueOf(++count)); + jsonSeqPojo.setEnd(seq.getEnd()); + jsonSeqPojo.setStart(seq.getStart()); + jsonSeqPojo.setName(name.toString()); + jsonSeqPojo.setSeq(seq.getSequenceAsString()); + jsonAlignmentPojo.getSeqs().add(jsonSeqPojo); + } + + /** + * TODO add logic to export Sequence features, non-auto-generated + * annotations, colour schemes + */ + return new com.json.JSONObject(jsonAlignmentPojo).toString() + .replaceAll("xstart", "xStart").replaceAll("xend", "xEnd"); + } + + public void parse(String jsonAlignmentString) + { + try + { + JSONParser jsonParser = new JSONParser(); + JSONObject alignmentJsonObj = (JSONObject) jsonParser + .parse(jsonAlignmentString); + JSONArray seqJsonArray = (JSONArray) alignmentJsonObj.get("seqs"); + String bioJsColourScheme = (String) alignmentJsonObj + .get("globalColorScheme"); + cs = getJalviewColorScheme(bioJsColourScheme); + + for (Iterator sequenceIter = seqJsonArray.iterator(); sequenceIter + .hasNext();) + { + JSONObject sequence = sequenceIter.next(); + String sequcenceString = sequence.get("seq").toString(); + Sequence seq = new Sequence(sequence.get("name").toString(), + sequcenceString, Integer.valueOf(sequence.get("start") + .toString()), Integer.valueOf(sequence.get("end") + .toString())); + + JSONArray jsonSeqArray = (JSONArray) sequence.get("features"); + SequenceFeature[] retrievedSeqFeatures = getJalviewSequenceFeatures( + jsonSeqArray, seq); + if (retrievedSeqFeatures != null) + { + seq.setSequenceFeatures(retrievedSeqFeatures); + } + seqs.add(seq); + } + } catch (Exception e) + { + e.printStackTrace(); + } + } + + public SequenceFeature[] getJalviewSequenceFeatures( + JSONArray jsonSeqFeatures, Sequence seq) + { + SequenceFeature[] seqFeatures = null; + int count = 0; + if (jsonSeqFeatures != null) + { + seqFeatures = new SequenceFeature[jsonSeqFeatures.size()]; + for (@SuppressWarnings("unchecked") + Iterator seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr + .hasNext();) + { + + SequenceFeature sequenceFeature = new SequenceFeature(); + JSONObject jsonFeature = seqFeatureItr.next(); + Long begin = (Long) jsonFeature.get("xStart"); + Long end = (Long) jsonFeature.get("xEnd"); + String type = (String) jsonFeature.get("text"); + // String color = (String) jsonFeature.get("fillColor"); + + sequenceFeature.setBegin(seq.findPosition(begin.intValue())); + sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1); + sequenceFeature.setType(type); + seqFeatures[count++] = sequenceFeature; + } + } + return seqFeatures; + } + + + private ColourSchemeI getJalviewColorScheme(String bioJsColourSchemeName) + { + ColourSchemeI jalviewColor = null; + for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper + .values()) + { + if (cs.getBioJsName().equals(bioJsColourSchemeName)) + { + jalviewColor = cs.getJvColourScheme(); + break; + } + } + return jalviewColor; + } + + public String getGlobalColorScheme() + { + return globalColorScheme; + } + + public void setGlobalColorScheme(String globalColorScheme) + { + this.globalColorScheme = globalColorScheme; + } +} diff --git a/src/jalview/json/binding/v1/BioJsAlignmentPojo.java b/src/jalview/json/binding/v1/AlignmentPojo.java similarity index 94% rename from src/jalview/json/binding/v1/BioJsAlignmentPojo.java rename to src/jalview/json/binding/v1/AlignmentPojo.java index 8e8747f..4391d80 100644 --- a/src/jalview/json/binding/v1/BioJsAlignmentPojo.java +++ b/src/jalview/json/binding/v1/AlignmentPojo.java @@ -16,25 +16,25 @@ import jalview.schemes.ZappoColourScheme; import java.util.ArrayList; -public class BioJsAlignmentPojo +public class AlignmentPojo { private String globalColorScheme = "none"; private String jalviewVersion; private String webStartUrl; - private ArrayList seqs = new ArrayList(); + private ArrayList seqs = new ArrayList(); - public BioJsAlignmentPojo() + public AlignmentPojo() { } - public ArrayList getSeqs() + public ArrayList getSeqs() { return seqs; } - public void setSeqs(ArrayList seqs) + public void setSeqs(ArrayList seqs) { this.seqs = seqs; } diff --git a/src/jalview/json/binding/v1/BioJsFeaturePojo.java b/src/jalview/json/binding/v1/FeaturePojo.java similarity index 91% rename from src/jalview/json/binding/v1/BioJsFeaturePojo.java rename to src/jalview/json/binding/v1/FeaturePojo.java index 3c2fdda..5e9ff84 100644 --- a/src/jalview/json/binding/v1/BioJsFeaturePojo.java +++ b/src/jalview/json/binding/v1/FeaturePojo.java @@ -1,6 +1,6 @@ package jalview.json.binding.v1; -public class BioJsFeaturePojo +public class FeaturePojo { private int xstart; @@ -11,7 +11,7 @@ public class BioJsFeaturePojo private String fillColor; - public BioJsFeaturePojo() + public FeaturePojo() { } diff --git a/src/jalview/json/binding/v1/BioJsSeqPojo.java b/src/jalview/json/binding/v1/SequencePojo.java similarity index 74% rename from src/jalview/json/binding/v1/BioJsSeqPojo.java rename to src/jalview/json/binding/v1/SequencePojo.java index bac8601..f993b13 100644 --- a/src/jalview/json/binding/v1/BioJsSeqPojo.java +++ b/src/jalview/json/binding/v1/SequencePojo.java @@ -3,7 +3,7 @@ package jalview.json.binding.v1; import java.util.ArrayList; -public class BioJsSeqPojo +public class SequencePojo { private String seq; @@ -15,13 +15,13 @@ public class BioJsSeqPojo private int end; - private ArrayList features = new ArrayList(); + private ArrayList features = new ArrayList(); - public BioJsSeqPojo() + public SequencePojo() { } - public BioJsSeqPojo(int start, int end, String id, String name, String seq) + public SequencePojo(int start, int end, String id, String name, String seq) { this.id = id; this.name = name; @@ -78,12 +78,12 @@ public class BioJsSeqPojo this.end = end; } - public ArrayList getFeatures() + public ArrayList getFeatures() { return features; } - public void setFeatures(ArrayList features) + public void setFeatures(ArrayList features) { this.features = features; } -- 1.7.10.2