JAL-1641 added support for persisting and retrieveing SequenceGroup
[jalview.git] / src / jalview / io / JSONFile.java
1 package jalview.io;
2
3 import jalview.api.FeaturesDisplayedI;
4 import jalview.datamodel.AlignmentAnnotation;
5 import jalview.datamodel.Annotation;
6 import jalview.datamodel.Sequence;
7 import jalview.datamodel.SequenceFeature;
8 import jalview.datamodel.SequenceGroup;
9 import jalview.datamodel.SequenceI;
10 import jalview.gui.AlignFrame;
11 import jalview.gui.Desktop;
12 import jalview.json.binding.v1.AlignmentAnnotationPojo;
13 import jalview.json.binding.v1.AlignmentPojo;
14 import jalview.json.binding.v1.AlignmentPojo.JalviewBioJsColorSchemeMapper;
15 import jalview.json.binding.v1.AnnotationPojo;
16 import jalview.json.binding.v1.FeaturePojo;
17 import jalview.json.binding.v1.SequenceGrpPojo;
18 import jalview.json.binding.v1.SequencePojo;
19 import jalview.schemes.ColourSchemeI;
20 import jalview.schemes.ColourSchemeProperty;
21 import jalview.viewmodel.AlignmentViewport;
22
23 import java.awt.Color;
24 import java.io.IOException;
25 import java.util.ArrayList;
26 import java.util.Hashtable;
27 import java.util.Iterator;
28
29 import org.json.simple.JSONArray;
30 import org.json.simple.JSONObject;
31 import org.json.simple.parser.JSONParser;
32
33 public class JSONFile extends AlignFile
34 {
35   private ColourSchemeI cs;
36
37   private String jalviewVersion;
38
39   private String webStartLaunchServletUrl = "http://www.jalview.org/services/launchApp";
40
41   public static final String FILE_EXT = "json";
42
43   public static final String FILE_DESC = "JSON";
44
45   private String globalColorScheme;
46
47   private Hashtable<String, Sequence> seqMap;
48
49   private FeaturesDisplayedI displayedFeatures;
50
51   private AlignmentViewport av;
52
53   private jalview.api.FeatureRenderer fr;
54
55   public JSONFile()
56   {
57     super();
58   }
59
60   public JSONFile(FileParse source) throws IOException
61   {
62     super(source);
63   }
64
65   public JSONFile(String inFile, String type) throws IOException
66   {
67     super(inFile, type);
68   }
69
70
71   @Override
72   public void parse() throws IOException
73   {
74     StringBuilder jsonStringBuilder = new StringBuilder();
75     String currentLine;
76     while ((currentLine = nextLine()) != null)
77     {
78       jsonStringBuilder.append(currentLine);
79     }
80     parse(jsonStringBuilder.toString());
81
82   }
83
84   @Override
85   public String print()
86   {
87     AlignmentPojo jsonAlignmentPojo = new AlignmentPojo();
88     if (Desktop.getCurrentAlignFrame() != null)
89     {
90       jsonAlignmentPojo.setGlobalColorScheme(ColourSchemeProperty
91               .getColourName(Desktop.getCurrentAlignFrame().getViewport()
92                       .getGlobalColourScheme()));
93       this.av = Desktop.getCurrentAlignFrame().getCurrentView();
94       this.fr = Desktop.getCurrentAlignFrame().alignPanel
95               .cloneFeatureRenderer();
96       displayedFeatures = av.getFeaturesDisplayed();
97       jsonAlignmentPojo
98               .setShowSeqFeatures(Desktop.getCurrentAlignFrame().showSeqFeatures
99                       .isSelected());
100     }
101     jsonAlignmentPojo.setJalviewVersion(jalviewVersion);
102     jsonAlignmentPojo.setWebStartUrl(webStartLaunchServletUrl);
103
104     if (seqGroups.size() > 0)
105     {
106       ArrayList<SequenceGrpPojo> sequenceGroupsPojo = new ArrayList<SequenceGrpPojo>();
107       for (SequenceGroup seqGrp : seqGroups)
108       {
109         SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
110         seqGrpPojo.setGroupName(seqGrp.getName());
111         seqGrpPojo.setColourScheme(ColourSchemeProperty
112                 .getColourName(seqGrp.cs));
113         seqGrpPojo.setColourText(seqGrp.getColourText());
114         seqGrpPojo.setDescription(seqGrp.getDescription());
115         seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
116         seqGrpPojo.setDisplayText(seqGrp.getDisplayText());
117         seqGrpPojo.setEndRes(seqGrp.getEndRes());
118         seqGrpPojo.setStartRes(seqGrp.getStartRes());
119         seqGrpPojo.setShowNonconserved(seqGrp.getShowNonconserved());
120         for(SequenceI seq : seqGrp.getSequences()){
121           seqGrpPojo.getSeqsHash().add(seq.getName() + "_" + seq.hashCode());
122         }
123         jsonAlignmentPojo.getSequenceGroups().add(seqGrpPojo);
124       }
125     }
126
127     for (AlignmentAnnotation annot : annotations)
128     {
129       AlignmentAnnotationPojo alignAnnotPojo = new AlignmentAnnotationPojo();
130       alignAnnotPojo.setDescription(annot.description);
131       alignAnnotPojo.setLabel(annot.label);
132       for (Annotation annotation : annot.annotations)
133       {
134         AnnotationPojo annotationPojo = new AnnotationPojo();
135         if (annotation != null)
136         {
137           annotationPojo.setDescription(annotation.description);
138           annotationPojo.setValue(annotation.value);
139           annotationPojo
140                   .setSecondaryStructure(annotation.secondaryStructure);
141           annotationPojo.setDisplayCharacter(annotation.displayCharacter);
142           alignAnnotPojo.getAnnotations().add(annotationPojo);
143         }
144         else
145         {
146           alignAnnotPojo.getAnnotations().add(annotationPojo);
147         }
148       }
149       jsonAlignmentPojo.getAlignmentAnnotation().add(alignAnnotPojo);
150     }
151
152     int count = 0;
153     for (SequenceI seq : seqs)
154     {
155       StringBuilder name = new StringBuilder();
156       name.append(seq.getName()).append("/").append(seq.getStart())
157               .append("-").append(seq.getEnd());
158
159       SequencePojo jsonSeqPojo = new SequencePojo();
160
161       jsonSeqPojo.setId(seq.getName() + "_" + seq.hashCode());
162       jsonSeqPojo.setOrder(++count);
163       jsonSeqPojo.setEnd(seq.getEnd());
164       jsonSeqPojo.setStart(seq.getStart());
165       jsonSeqPojo.setName(name.toString());
166       jsonSeqPojo.setSeq(seq.getSequenceAsString());
167       jsonAlignmentPojo.getSeqs().add(jsonSeqPojo);
168
169       if (seq.getDatasetSequence() != null
170               && seq.getDatasetSequence().getSequenceFeatures() != null)
171       {
172         ArrayList<FeaturePojo> seqFeaturesPojo = new ArrayList<FeaturePojo>();
173         for (SequenceFeature sf : seq.getDatasetSequence()
174                 .getSequenceFeatures())
175         {
176
177           if (displayedFeatures != null
178                   && displayedFeatures.isVisible(sf.getType()))
179           {
180
181             String fillColor = ((fr != null) ? jalview.util.Format
182                     .getHexString(fr.findFeatureColour(Color.white, seq,
183                             seq.findIndex(sf.getBegin()))) : null);
184             FeaturePojo jsonFeature = new FeaturePojo();
185             jsonFeature.setXstart(seq.findIndex(sf.getBegin()) - 1);
186             jsonFeature.setXend(seq.findIndex(sf.getEnd()));
187             jsonFeature.setType(sf.getType());
188             jsonFeature.setDescription(sf.getDescription());
189             jsonFeature.setLinks(sf.links);
190             jsonFeature.setOtherDetails(sf.otherDetails);
191             jsonFeature.setScore(sf.getScore());
192             jsonFeature.setFillColor(fillColor);
193             jsonFeature.setFeatureGroup(sf.getFeatureGroup());
194             seqFeaturesPojo.add(jsonFeature);
195           }
196         }
197         jsonSeqPojo.setFeatures(seqFeaturesPojo);
198       }
199     }
200     return new com.json.JSONObject(jsonAlignmentPojo).toString()
201             .replaceAll("xstart", "xStart").replaceAll("xend", "xEnd");
202   }
203
204   public void parse(String jsonAlignmentString)
205   {
206     try
207     {
208       JSONParser jsonParser = new JSONParser();
209       JSONObject alignmentJsonObj = (JSONObject) jsonParser
210               .parse(jsonAlignmentString);
211       JSONArray seqJsonArray = (JSONArray) alignmentJsonObj.get("seqs");
212       JSONArray alAnnotJsonArray = (JSONArray) alignmentJsonObj.get("alignmentAnnotation");
213       JSONArray seqGrpJsonArray = (JSONArray) alignmentJsonObj.get("sequenceGroups");
214       String jsColourScheme = (String) alignmentJsonObj
215               .get("globalColorScheme");
216       Boolean showFeatures = Boolean.valueOf(alignmentJsonObj.get(
217               "showSeqFeatures").toString());
218       cs = getJalviewColorScheme(jsColourScheme);
219       seqMap = new Hashtable<String, Sequence>();
220       Desktop.setCurrentGlobalColourScheme(cs);
221       Desktop.setCurrentSeqFeaturesVisible(showFeatures);
222       for (Iterator<JSONObject> sequenceIter = seqJsonArray.iterator(); sequenceIter
223               .hasNext();)
224       {
225         JSONObject sequence = sequenceIter.next();
226         String sequcenceString = sequence.get("seq").toString();
227         String sequenceName = sequence.get("name").toString();
228         String seqUniqueId = sequence.get("id").toString();
229         int start = Integer.valueOf(sequence.get("start").toString());
230         int end = Integer.valueOf(sequence.get("end").toString());
231         Sequence seq = new Sequence(sequenceName, sequcenceString, start,
232                 end);
233         JSONArray jsonSeqArray = (JSONArray) sequence.get("features");
234         SequenceFeature[] retrievedSeqFeatures = getJalviewSequenceFeatures(
235                 jsonSeqArray, seq);
236         if (retrievedSeqFeatures != null)
237         {
238           seq.setSequenceFeatures(retrievedSeqFeatures);
239         }
240         seqs.add(seq);
241         seqMap.put(seqUniqueId, seq);
242       }
243       
244       for (Iterator<JSONObject> seqGrpIter = seqGrpJsonArray.iterator(); seqGrpIter
245               .hasNext();)
246       {
247         JSONObject seqGrpObj = seqGrpIter.next();
248         String grpName = seqGrpObj.get("groupName").toString();
249         String colourScheme = seqGrpObj.get("colourScheme").toString();
250         String description = (seqGrpObj.get("description") == null) ? null
251                 : seqGrpObj.get("description").toString();
252         boolean displayBoxes = Boolean.valueOf(seqGrpObj
253                 .get("displayBoxes").toString());
254         boolean displayText = Boolean.valueOf(seqGrpObj.get("displayText")
255                 .toString());
256         boolean colourText = Boolean.valueOf(seqGrpObj.get("colourText")
257                 .toString());
258         boolean showNonconserved = Boolean.valueOf(seqGrpObj.get(
259                 "showNonconserved").toString());
260         int startRes = Integer
261                 .valueOf(seqGrpObj.get("startRes").toString());
262         int endRes = Integer.valueOf(seqGrpObj.get("endRes").toString());
263         JSONArray seqsHashArray = (JSONArray) seqGrpObj.get("seqsHash");
264
265         ArrayList<SequenceI> grpSeqs = new ArrayList<SequenceI>();
266         if (seqsHashArray.size() > 0)
267         {
268           Iterator<String> seqHashIter = seqsHashArray.iterator();
269           while (seqHashIter.hasNext())
270           {
271             String seqHash = seqHashIter.next();
272             Sequence sequence = seqMap.get(seqHash);
273             if (sequence != null)
274             {
275               grpSeqs.add(sequence);
276             }
277           }
278         }
279         ColourSchemeI scheme = getJalviewColorScheme(colourScheme);
280         SequenceGroup seqGrp = new SequenceGroup(grpSeqs, grpName, scheme,
281                 displayBoxes, displayText, colourText, startRes, endRes);
282         seqGrp.setShowNonconserved(showNonconserved);
283         seqGrp.setDescription(description);
284         this.seqGroups.add(seqGrp);
285
286       }
287
288
289       for (Iterator<JSONObject> alAnnotIter = alAnnotJsonArray.iterator(); alAnnotIter
290               .hasNext();)
291       {
292         JSONObject alAnnot = alAnnotIter.next();
293         JSONArray annotJsonArray = (JSONArray) alAnnot
294                 .get("annotations");
295         Annotation[] annotations = new Annotation[annotJsonArray.size()];
296         int count = 0;
297         for (Iterator<JSONObject> annotIter = annotJsonArray.iterator(); annotIter
298                 .hasNext();)
299         {
300           JSONObject annot = annotIter.next();
301           if (annot == null)
302           {
303             annotations[count] = null;
304           }
305           else
306           {
307             float val = annot.get("value") == null ? null
308                     : Float.valueOf(annot.get("value")
309                     .toString());
310             String desc = annot.get("description") == null ? null : annot
311                     .get("description").toString();
312
313             char ss = annot.get("secondaryStructure") == null ? null
314                     : annot
315                     .get("secondaryStructure").toString().charAt(0);
316             String displayChar = annot.get(
317                     "displayCharacter").toString();
318
319             annotations[count] = new Annotation(displayChar, desc, ss, val);
320           }
321           ++count;
322         }
323
324         AlignmentAnnotation alignAnnot = new AlignmentAnnotation(alAnnot
325                 .get("label").toString(), alAnnot.get("description")
326                 .toString(), annotations);
327         this.annotations.add(alignAnnot);
328       }
329
330     } catch (Exception e)
331     {
332       e.printStackTrace();
333     }
334   }
335
336   public SequenceFeature[] getJalviewSequenceFeatures(
337           JSONArray jsonSeqFeatures, Sequence seq)
338   {
339     SequenceFeature[] seqFeatures = null;
340     int count = 0;
341     if (jsonSeqFeatures != null)
342     {
343       seqFeatures = new SequenceFeature[jsonSeqFeatures.size()];
344       for (@SuppressWarnings("unchecked")
345       Iterator<JSONObject> seqFeatureItr = jsonSeqFeatures.iterator(); seqFeatureItr
346               .hasNext();)
347       {
348
349         SequenceFeature sequenceFeature = new SequenceFeature();
350         JSONObject jsonFeature = seqFeatureItr.next();
351         Long begin = (Long) jsonFeature.get("xStart");
352         Long end = (Long) jsonFeature.get("xEnd");
353         String type = (String) jsonFeature.get("type");
354         String color = (String) jsonFeature.get("fillColor");
355         String featureGrp = (String) jsonFeature.get("featureGroup");
356         String descripiton = (String) jsonFeature.get("description");
357         Float score = Float.valueOf(jsonFeature.get("score").toString());
358         // Hashtable otherDetails = (Hashtable) jsonFeature
359         // .get("otherDetails");
360         // Vector<String> links = (Vector<String>) jsonFeature.get("links");
361
362         // sequenceFeature.links = links;
363         // sequenceFeature.otherDetails = otherDetails;
364         sequenceFeature.setScore(score);
365         sequenceFeature.setDescription(descripiton);
366
367         sequenceFeature.setBegin(seq.findPosition(begin.intValue()));
368         sequenceFeature.setEnd(seq.findPosition(end.intValue()) - 1);
369         sequenceFeature.setType(type);
370         seqFeatures[count++] = sequenceFeature;
371       }
372     }
373     return seqFeatures;
374   }
375
376   private ColourSchemeI getJalviewColorScheme(String bioJsColourSchemeName)
377   {
378     ColourSchemeI jalviewColor = null;
379     for (JalviewBioJsColorSchemeMapper cs : JalviewBioJsColorSchemeMapper
380             .values())
381     {
382       if (cs.getBioJsName().equalsIgnoreCase(bioJsColourSchemeName))
383       {
384         jalviewColor = cs.getJvColourScheme();
385         break;
386       }
387     }
388     return jalviewColor;
389   }
390
391   public void LoadAlignmentFeatures(AlignFrame af)
392   {
393     af.setShowSeqFeatures(Desktop.isCurrentSeqFeaturesVisible());
394     af.changeColour(Desktop.getCurrentGlobalColourScheme());
395     af.setMenusForViewport();
396   }
397
398   public String getGlobalColorScheme()
399   {
400     return globalColorScheme;
401   }
402
403   public void setGlobalColorScheme(String globalColorScheme)
404   {
405     this.globalColorScheme = globalColorScheme;
406   }
407 }