X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fio%2FSequenceAnnotationReport.java;h=5ada3554e45fee13d1dff040e8bd785ab3a000f3;hb=1beac3545a78d4c5c3274dbb53296708d693efe0;hp=850b1dcfb64f685c8e6d36514bf943a203d5fd8b;hpb=d0d8e3e2f528581af454e5b2a51372a9f4677114;p=jalview.git diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index 850b1dc..5ada355 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -20,13 +20,16 @@ */ package jalview.io; +import jalview.api.FeatureColourI; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.SequenceFeature; import jalview.datamodel.SequenceI; -import jalview.io.gff.GffConstants; import jalview.util.MessageManager; +import jalview.util.StringUtils; import jalview.util.UrlLink; +import jalview.viewmodel.seqfeatures.FeatureRendererModel; import java.util.Arrays; import java.util.Collection; @@ -57,7 +60,8 @@ public class SequenceAnnotationReport final String linkImageURL; /* - * Comparator to order DBRefEntry by Source + accession id (case-insensitive) + * Comparator to order DBRefEntry by Source + accession id (case-insensitive), + * with 'Primary' sources placed before others, and 'chromosome' first of all */ private static Comparator comparator = new Comparator() { @@ -65,6 +69,14 @@ public class SequenceAnnotationReport @Override public int compare(DBRefEntry ref1, DBRefEntry ref2) { + if (ref1.isChromosome()) + { + return -1; + } + if (ref2.isChromosome()) + { + return 1; + } String s1 = ref1.getSource(); String s2 = ref2.getSource(); boolean s1Primary = isPrimarySource(s1); @@ -105,9 +117,9 @@ public class SequenceAnnotationReport } }; - public SequenceAnnotationReport(String linkImageURL) + public SequenceAnnotationReport(String linkURL) { - this.linkImageURL = linkImageURL; + this.linkImageURL = linkURL; } /** @@ -119,13 +131,13 @@ public class SequenceAnnotationReport * @param minmax */ public void appendFeatures(final StringBuilder sb, int rpos, - List features, Map minmax) + List features, FeatureRendererModel fr) { if (features != null) { for (SequenceFeature feature : features) { - appendFeature(sb, rpos, minmax, feature); + appendFeature(sb, rpos, fr, feature); } } } @@ -139,10 +151,9 @@ public class SequenceAnnotationReport * @param feature */ void appendFeature(final StringBuilder sb, int rpos, - Map minmax, SequenceFeature feature) + FeatureRendererModel fr, SequenceFeature feature) { - String tmpString; - if (feature.getType().equals("disulfide bond")) + if (feature.isContactFeature()) { if (feature.getBegin() == rpos || feature.getEnd() == rpos) { @@ -150,102 +161,95 @@ public class SequenceAnnotationReport { sb.append("
"); } - sb.append("disulfide bond ").append(feature.getBegin()).append(":") - .append(feature.getEnd()); + sb.append(feature.getType()).append(" ").append(feature.getBegin()) + .append(":").append(feature.getEnd()); } + return; + } + + if (sb.length() > 6) + { + sb.append("
"); } - else + // TODO: remove this hack to display link only features + boolean linkOnly = feature.getValue("linkonly") != null; + if (!linkOnly) { - if (sb.length() > 6) + sb.append(feature.getType()).append(" "); + if (rpos != 0) { - sb.append("
"); + // we are marking a positional feature + sb.append(feature.begin); } - // TODO: remove this hack to display link only features - boolean linkOnly = feature.getValue("linkonly") != null; - if (!linkOnly) + if (feature.begin != feature.end) { - sb.append(feature.getType()).append(" "); - if (rpos != 0) - { - // we are marking a positional feature - sb.append(feature.begin); - } - if (feature.begin != feature.end) - { - sb.append(" ").append(feature.end); - } + sb.append(" ").append(feature.end); + } - if (feature.getDescription() != null - && !feature.description.equals(feature.getType())) - { - tmpString = feature.getDescription(); - String tmp2up = tmpString.toUpperCase(); - int startTag = tmp2up.indexOf(""); - if (startTag > -1) - { - tmpString = tmpString.substring(startTag + 6); - tmp2up = tmp2up.substring(startTag + 6); - } - int endTag = tmp2up.indexOf(""); - if (endTag > -1) - { - tmpString = tmpString.substring(0, endTag); - tmp2up = tmp2up.substring(0, endTag); - } - endTag = tmp2up.indexOf(""); - if (endTag > -1) - { - tmpString = tmpString.substring(0, endTag); - } + String description = feature.getDescription(); + if (description != null && !description.equals(feature.getType())) + { + description = StringUtils.stripHtmlTags(description); + sb.append("; ").append(description); + } - if (startTag > -1) - { - sb.append("; ").append(tmpString); - } - else - { - if (tmpString.indexOf("<") > -1 || tmpString.indexOf(">") > -1) - { - // The description does not specify html is to - // be used, so we must remove < > symbols - tmpString = tmpString.replaceAll("<", "<"); - tmpString = tmpString.replaceAll(">", ">"); + if (showScore(feature, fr)) + { + sb.append(" Score=").append(String.valueOf(feature.getScore())); + } + String status = (String) feature.getValue("status"); + if (status != null && status.length() > 0) + { + sb.append("; (").append(status).append(")"); + } - sb.append("; "); - sb.append(tmpString); - } - else - { - sb.append("; ").append(tmpString); - } - } - } - // check score should be shown - if (!Float.isNaN(feature.getScore())) + /* + * add attribute value if coloured by attribute + */ + if (fr != null) + { + FeatureColourI fc = fr.getFeatureColours().get(feature.getType()); + if (fc != null && fc.isColourByAttribute()) { - float[][] rng = (minmax == null) ? null : ((float[][]) minmax - .get(feature.getType())); - if (rng != null && rng[0] != null && rng[0][0] != rng[0][1]) + String[] attName = fc.getAttributeName(); + String attVal = feature.getValueAsString(attName); + if (attVal != null) { - sb.append(" Score=" + feature.getScore()); + sb.append("; ").append(String.join(":", attName)).append("=") + .append(attVal); } } - String status = (String) feature.getValue("status"); - if (status != null && status.length() > 0) - { - sb.append("; (").append(status).append(")"); - } - String clinSig = (String) feature - .getValue(GffConstants.CLINICAL_SIGNIFICANCE); - if (clinSig != null) - { - sb.append("; ").append(clinSig); - } } } } /** + * Answers true if score should be shown, else false. Score is shown if it is + * not NaN, and the feature type has a non-trivial min-max score range + */ + boolean showScore(SequenceFeature feature, FeatureRendererModel fr) + { + if (Float.isNaN(feature.getScore())) + { + return false; + } + if (fr == null) + { + return true; + } + float[][] minMax = fr.getMinMax().get(feature.getType()); + + /* + * minMax[0] is the [min, max] score range for positional features + */ + if (minMax == null || minMax[0] == null || minMax[0][0] == minMax[0][1]) + { + return false; + } + return true; + } + + /** * Format and appends any hyperlinks for the sequence feature to the string * buffer * @@ -276,8 +280,7 @@ public class SequenceAnnotationReport + (urllink.get(0).toLowerCase() .equals(urllink.get(1).toLowerCase()) ? urllink .get(0) : (urllink.get(0) + ":" + urllink - .get(1))) - + "
"); + .get(1))) + "
"); } } catch (Exception x) { @@ -300,7 +303,7 @@ public class SequenceAnnotationReport */ Collection> createLinksFrom(SequenceI seq, String link) { - Map> urlSets = new LinkedHashMap>(); + Map> urlSets = new LinkedHashMap<>(); UrlLink urlLink = new UrlLink(link); if (!urlLink.isValid()) { @@ -315,10 +318,10 @@ public class SequenceAnnotationReport public void createSequenceAnnotationReport(final StringBuilder tip, SequenceI sequence, boolean showDbRefs, boolean showNpFeats, - Map minmax) + FeatureRendererModel fr) { createSequenceAnnotationReport(tip, sequence, showDbRefs, showNpFeats, - minmax, false); + fr, false); } /** @@ -333,13 +336,13 @@ public class SequenceAnnotationReport * whether to include database references for the sequence * @param showNpFeats * whether to include non-positional sequence features - * @param minmax + * @param fr * @param summary * @return */ int createSequenceAnnotationReport(final StringBuilder sb, SequenceI sequence, boolean showDbRefs, boolean showNpFeats, - Map minmax, boolean summary) + FeatureRendererModel fr, boolean summary) { String tmp; sb.append(""); @@ -351,113 +354,148 @@ public class SequenceAnnotationReport sb.append("
").append(tmp); maxWidth = Math.max(maxWidth, tmp.length()); } + SequenceI ds = sequence; while (ds.getDatasetSequence() != null) { ds = ds.getDatasetSequence(); } - DBRefEntry[] dbrefs = ds.getDBRefs(); - if (showDbRefs && dbrefs != null) + + /* + * add any annotation scores + */ + AlignmentAnnotation[] anns = ds.getAnnotation(); + for (int i = 0; anns != null && i < anns.length; i++) { - // note this sorts the refs held on the sequence! - Arrays.sort(dbrefs, comparator); - boolean ellipsis = false; - String source = null; - String lastSource = null; - int countForSource = 0; - int sourceCount = 0; - boolean moreSources = false; - int lineLength = 0; - - for (DBRefEntry ref : dbrefs) + AlignmentAnnotation aa = anns[i]; + if (aa != null && aa.hasScore() && aa.sequenceRef != null) { - source = ref.getSource(); - if (source == null) - { - // shouldn't happen - continue; - } - boolean sourceChanged = !source.equals(lastSource); - if (sourceChanged) - { - lineLength = 0; - countForSource = 0; - sourceCount++; - } - if (sourceCount > MAX_SOURCES && summary) - { - ellipsis = true; - moreSources = true; - break; - } - lastSource = source; - countForSource++; - if (countForSource == 1 || !summary) - { - sb.append("
"); - } - if (countForSource <= MAX_REFS_PER_SOURCE || !summary) - { - String accessionId = ref.getAccessionId(); - lineLength += accessionId.length() + 1; - if (countForSource > 1 && summary) - { - sb.append(", ").append(accessionId); - lineLength++; - } - else - { - sb.append(source).append(" ").append(accessionId); - lineLength += source.length(); - } - maxWidth = Math.max(maxWidth, lineLength); - } - if (countForSource == MAX_REFS_PER_SOURCE && summary) - { - sb.append(COMMA).append(ELLIPSIS); - ellipsis = true; - } - } - if (moreSources) - { - sb.append("
").append(ELLIPSIS).append(COMMA).append(source) - .append(COMMA).append(ELLIPSIS); - } - if (ellipsis) - { - sb.append("
("); - sb.append(MessageManager.getString("label.output_seq_details")); - sb.append(")"); + sb.append("
").append(aa.label).append(": ") + .append(aa.getScore()); } } + if (showDbRefs) + { + maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary)); + } + /* * add non-positional features if wanted */ - SequenceFeature[] features = sequence.getSequenceFeatures(); - if (showNpFeats && features != null) + if (showNpFeats) { - for (int i = 0; i < features.length; i++) + for (SequenceFeature sf : sequence.getFeatures() + .getNonPositionalFeatures()) { - if (features[i].begin == 0 && features[i].end == 0) - { - int sz = -sb.length(); - appendFeature(sb, 0, minmax, features[i]); - sz += sb.length(); - maxWidth = Math.max(maxWidth, sz); - } + int sz = -sb.length(); + appendFeature(sb, 0, fr, sf); + sz += sb.length(); + maxWidth = Math.max(maxWidth, sz); } } sb.append("
"); return maxWidth; } + /** + * A helper method that appends any DBRefs, returning the maximum line length + * added + * + * @param sb + * @param ds + * @param summary + * @return + */ + protected int appendDbRefs(final StringBuilder sb, SequenceI ds, + boolean summary) + { + DBRefEntry[] dbrefs = ds.getDBRefs(); + if (dbrefs == null) + { + return 0; + } + + // note this sorts the refs held on the sequence! + Arrays.sort(dbrefs, comparator); + boolean ellipsis = false; + String source = null; + String lastSource = null; + int countForSource = 0; + int sourceCount = 0; + boolean moreSources = false; + int maxLineLength = 0; + int lineLength = 0; + + for (DBRefEntry ref : dbrefs) + { + source = ref.getSource(); + if (source == null) + { + // shouldn't happen + continue; + } + boolean sourceChanged = !source.equals(lastSource); + if (sourceChanged) + { + lineLength = 0; + countForSource = 0; + sourceCount++; + } + if (sourceCount > MAX_SOURCES && summary) + { + ellipsis = true; + moreSources = true; + break; + } + lastSource = source; + countForSource++; + if (countForSource == 1 || !summary) + { + sb.append("
"); + } + if (countForSource <= MAX_REFS_PER_SOURCE || !summary) + { + String accessionId = ref.getAccessionId(); + lineLength += accessionId.length() + 1; + if (countForSource > 1 && summary) + { + sb.append(", ").append(accessionId); + lineLength++; + } + else + { + sb.append(source).append(" ").append(accessionId); + lineLength += source.length(); + } + maxLineLength = Math.max(maxLineLength, lineLength); + } + if (countForSource == MAX_REFS_PER_SOURCE && summary) + { + sb.append(COMMA).append(ELLIPSIS); + ellipsis = true; + } + } + if (moreSources) + { + sb.append("
").append(source).append(COMMA).append(ELLIPSIS); + } + if (ellipsis) + { + sb.append("
("); + sb.append(MessageManager.getString("label.output_seq_details")); + sb.append(")"); + } + + return maxLineLength; + } + public void createTooltipAnnotationReport(final StringBuilder tip, SequenceI sequence, boolean showDbRefs, boolean showNpFeats, - Map minmax) + FeatureRendererModel fr) { int maxWidth = createSequenceAnnotationReport(tip, sequence, - showDbRefs, showNpFeats, minmax, true); + showDbRefs, showNpFeats, fr, true); if (maxWidth > 60) {