/*
* Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
* Copyright (C) $$Year-Rel$$ 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 .
* The Jalview Authors are detailed in the 'AUTHORS' file.
*/
package jalview.io;
import jalview.api.AlignExportSettingsI;
import jalview.api.AlignViewportI;
import jalview.api.AlignmentViewPanel;
import jalview.api.ComplexAlignFile;
import jalview.api.FeatureRenderer;
import jalview.api.FeatureSettingsModelI;
import jalview.api.FeaturesDisplayedI;
import jalview.bin.BuildDetails;
import jalview.datamodel.AlignExportSettingsAdapter;
import jalview.datamodel.AlignmentAnnotation;
import jalview.datamodel.AlignmentI;
import jalview.datamodel.Annotation;
import jalview.datamodel.HiddenColumns;
import jalview.datamodel.HiddenSequences;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceGroup;
import jalview.datamodel.SequenceI;
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.renderer.seqfeatures.FeatureColourFinder;
import jalview.schemes.ColourSchemeProperty;
import jalview.schemes.JalviewColourScheme;
import jalview.schemes.ResidueColourScheme;
import jalview.util.ColorUtils;
import jalview.util.Format;
import jalview.util.JSONUtils;
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;
import java.util.List;
import java.util.Map;
import java.util.Vector;
public class JSONFile extends AlignFile implements ComplexAlignFile
{
private static String version = new BuildDetails().getVersion();
private String webstartUrl = "https://www.jalview.org/services/launchApp";
private String application = "Jalview";
private String globalColourScheme;
private boolean showSeqFeatures;
private Hashtable seqMap;
private FeaturesDisplayedI displayedFeatures;
private FeatureRenderer fr;
private HiddenColumns hiddenColumns;
private List hiddenSeqRefs;
private ArrayList hiddenSequences;
private final static String TCOFFEE_SCORE = "TCoffeeScore";
public JSONFile()
{
super();
}
public JSONFile(FileParse source) throws IOException
{
super(source);
}
public JSONFile(String inFile, DataSourceType sourceType)
throws IOException
{
super(inFile, sourceType);
}
@Override
public void parse() throws IOException
{
parse(getReader());
}
@Override
public String print(SequenceI[] sqs, boolean jvsuffix)
{
String jsonOutput = null;
try
{
AlignmentPojo jsonAlignmentPojo = new AlignmentPojo();
AlignExportSettingsI exportSettings = getExportSettings();
/*
* if no export settings were supplied, provide an 'export all' setting
*/
if (exportSettings == null)
{
exportSettings = new AlignExportSettingsAdapter(true);
}
int count = 0;
for (SequenceI seq : sqs)
{
StringBuilder name = new StringBuilder();
name.append(seq.getName()).append("/").append(seq.getStart())
.append("-").append(seq.getEnd());
SequencePojo jsonSeqPojo = new SequencePojo();
jsonSeqPojo.setId(String.valueOf(seq.hashCode()));
jsonSeqPojo.setOrder(++count);
jsonSeqPojo.setEnd(seq.getEnd());
jsonSeqPojo.setStart(seq.getStart());
jsonSeqPojo.setName(name.toString());
jsonSeqPojo.setSeq(seq.getSequenceAsString());
jsonAlignmentPojo.getSeqs().add(jsonSeqPojo);
}
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)
{
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())
{
jsonAlignmentPojo
.setAlignAnnotation(annotationToJsonPojo(annotations));
}
else
{
// These color schemes require annotation, disable them if annotations
// are not exported
if (globalColourScheme
.equalsIgnoreCase(JalviewColourScheme.RNAHelices.toString())
|| globalColourScheme.equalsIgnoreCase(
JalviewColourScheme.TCoffee.toString()))
{
jsonAlignmentPojo.setGlobalColorScheme(ResidueColourScheme.NONE);
}
}
if (exportSettings.isExportFeatures())
{
jsonAlignmentPojo.setSeqFeatures(sequenceFeatureToJsonPojo(sqs));
}
if (exportSettings.isExportGroups() && seqGroups != null
&& seqGroups.size() > 0)
{
for (SequenceGroup seqGrp : seqGroups)
{
SequenceGrpPojo seqGrpPojo = new SequenceGrpPojo();
seqGrpPojo.setGroupName(seqGrp.getName());
seqGrpPojo.setColourScheme(ColourSchemeProperty
.getColourName(seqGrp.getColourScheme()));
seqGrpPojo.setColourText(seqGrp.getColourText());
seqGrpPojo.setDescription(seqGrp.getDescription());
seqGrpPojo.setDisplayBoxes(seqGrp.getDisplayBoxes());
seqGrpPojo.setDisplayText(seqGrp.getDisplayText());
seqGrpPojo.setEndRes(seqGrp.getEndRes());
seqGrpPojo.setStartRes(seqGrp.getStartRes());
seqGrpPojo.setShowNonconserved(seqGrp.getShowNonconserved());
for (SequenceI seq : seqGrp.getSequences())
{
seqGrpPojo.getSequenceRefs()
.add(String.valueOf(seq.hashCode()));
}
jsonAlignmentPojo.getSeqGroups().add(seqGrpPojo);
}
}
jsonOutput = JSONUtils.stringify(jsonAlignmentPojo);
return jsonOutput.replaceAll("xstart", "xStart").replaceAll("xend",
"xEnd");
} catch (Exception e)
{
e.printStackTrace();
}
return jsonOutput;
}
public String[] getHiddenSections()
{
String[] hiddenSections = new String[2];
if (getViewport() == null)
{
return null;
}
// hidden column business
if (getViewport().hasHiddenColumns())
{
hiddenSections[0] = getViewport().getAlignment().getHiddenColumns()
.regionsToString(";", "-");
}
// 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;
}
protected List sequenceFeatureToJsonPojo(
SequenceI[] sqs)
{
displayedFeatures = (fr == null) ? null : fr.getFeaturesDisplayed();
List sequenceFeaturesPojo = new ArrayList<>();
if (sqs == null)
{
return sequenceFeaturesPojo;
}
FeatureColourFinder finder = new FeatureColourFinder(fr);
String[] visibleFeatureTypes = displayedFeatures == null ? null
: displayedFeatures.getVisibleFeatures().toArray(
new String[displayedFeatures.getVisibleFeatureCount()]);
for (SequenceI seq : sqs)
{
/*
* get all features currently visible (and any non-positional features)
*/
List seqFeatures = seq.getFeatures()
.getAllFeatures(visibleFeatureTypes);
for (SequenceFeature sf : seqFeatures)
{
SequenceFeaturesPojo jsonFeature = new SequenceFeaturesPojo(
String.valueOf(seq.hashCode()));
String featureColour = (fr == null) ? null
: Format.getHexString(finder.findFeatureColour(Color.white,
seq, seq.findIndex(sf.getBegin())));
int xStart = sf.getBegin() == 0 ? 0
: seq.findIndex(sf.getBegin()) - 1;
int xEnd = sf.getEnd() == 0 ? 0 : seq.findIndex(sf.getEnd());
jsonFeature.setXstart(xStart);
jsonFeature.setXend(xEnd);
jsonFeature.setType(sf.getType());
jsonFeature.setDescription(sf.getDescription());
jsonFeature.setLinks(sf.links);
jsonFeature.setOtherDetails(sf.otherDetails);
jsonFeature.setScore(sf.getScore());
jsonFeature.setFillColor(featureColour);
jsonFeature.setFeatureGroup(sf.getFeatureGroup());
sequenceFeaturesPojo.add(jsonFeature);
}
}
return sequenceFeaturesPojo;
}
public static List annotationToJsonPojo(
Vector annotations)
{
List jsonAnnotations = new ArrayList<>();
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();
if (annotation != null)
{
annotationPojo.setDescription(annotation.description);
annotationPojo.setValue(annotation.value);
annotationPojo
.setSecondaryStructure(annotation.secondaryStructure);
String displayChar = annotation.displayCharacter == null ? null
: annotation.displayCharacter;
// jalview.bin.Console.outPrintln("--------------------->[" +
// displayChar + "]");
annotationPojo.setDisplayCharacter(displayChar);
if (annotation.colour != null)
{
annotationPojo.setColour(
jalview.util.Format.getHexString(annotation.colour));
}
alignAnnotPojo.getAnnotations().add(annotationPojo);
}
else
{
if (annot.getCalcId() != null
&& annot.getCalcId().equalsIgnoreCase(TCOFFEE_SCORE))
{
// do nothing
}
else
{
alignAnnotPojo.getAnnotations().add(annotationPojo);
}
}
}
jsonAnnotations.add(alignAnnotPojo);
}
return jsonAnnotations;
}
@SuppressWarnings("unchecked")
public JSONFile parse(Reader jsonAlignmentString)
{
try
{
Map alignmentJsonObj = (Map) JSONUtils
.parse(jsonAlignmentString);
List