X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fio%2FSequenceAnnotationReport.java;h=1a5072dde534ff8b4b5e7efe418af1ea61f3deb5;hb=c794c5033adeee182b03a5ea92c0a7495a29661f;hp=df28ea3757f9e76e58d5064a71ec689014cc9a47;hpb=586b87fca07c53c935ffe67827e498eb80fad4bf;p=jalview.git diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index df28ea3..1a5072d 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -20,7 +20,14 @@ */ package jalview.io; +import java.util.Collection; +import java.util.Comparator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + import jalview.api.FeatureColourI; +import jalview.datamodel.AlignmentAnnotation; import jalview.datamodel.DBRefEntry; import jalview.datamodel.DBRefSource; import jalview.datamodel.GeneLociI; @@ -32,13 +39,6 @@ import jalview.util.StringUtils; import jalview.util.UrlLink; import jalview.viewmodel.seqfeatures.FeatureRendererModel; -import java.util.Arrays; -import java.util.Collection; -import java.util.Comparator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - /** * generate HTML reports for a sequence * @@ -56,17 +56,15 @@ public class SequenceAnnotationReport private static final int MAX_SOURCES = 40; - private static final String[][] PRIMARY_SOURCES = new String[][] { - DBRefSource.CODINGDBS, DBRefSource.DNACODINGDBS, - DBRefSource.PROTEINDBS }; + private static String linkImageURL; - final String linkImageURL; + // public static final String[][] PRIMARY_SOURCES moved to DBRefSource.java /* * 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<>() + private static Comparator comparator = new Comparator() { @Override @@ -82,8 +80,8 @@ public class SequenceAnnotationReport } String s1 = ref1.getSource(); String s2 = ref2.getSource(); - boolean s1Primary = isPrimarySource(s1); - boolean s2Primary = isPrimarySource(s2); + boolean s1Primary = DBRefSource.isPrimarySource(s1); + boolean s2Primary = DBRefSource.isPrimarySource(s2); if (s1Primary && !s2Primary) { return -1; @@ -104,59 +102,91 @@ public class SequenceAnnotationReport return comp; } - private boolean isPrimarySource(String source) - { - for (String[] primary : PRIMARY_SOURCES) - { - for (String s : primary) - { - if (source.equals(s)) - { - return true; - } - } - } - return false; - } +// private boolean isPrimarySource(String source) +// { +// for (String[] primary : DBRefSource.PRIMARY_SOURCES) +// { +// for (String s : primary) +// { +// if (source.equals(s)) +// { +// return true; +// } +// } +// } +// return false; +// } }; - public SequenceAnnotationReport(String linkURL) + private boolean forTooltip; + + /** + * Constructor given a flag which affects behaviour + *
    + *
  • if true, generates feature details suitable to show in a tooltip
  • + *
  • if false, generates feature details in a form suitable for the sequence + * details report
  • + *
+ * + * @param isForTooltip + */ + public SequenceAnnotationReport(boolean isForTooltip) { - this.linkImageURL = linkURL; + this.forTooltip = isForTooltip; + if (linkImageURL == null) + { + linkImageURL = getClass().getResource("/images/link.gif").toString(); + } } /** - * Append text for the list of features to the tooltip + * Append text for the list of features to the tooltip. Returns the number of + * features not added if maxlength limit is (or would have been) reached. * * @param sb * @param residuePos * @param features * @param minmax + * @param maxlength */ - public void appendFeatures(final StringBuilder sb, int residuePos, - List features, FeatureRendererModel fr) + public int appendFeatures(final StringBuilder sb, + int residuePos, List features, + FeatureRendererModel fr, int maxlength) { - for (SequenceFeature feature : features) + for (int i = 0; i < features.size(); i++) { - appendFeature(sb, residuePos, fr, feature, null); + SequenceFeature feature = features.get(i); + if (appendFeature(sb, residuePos, fr, feature, null, maxlength)) + { + return features.size() - i; + } } + return 0; } /** - * Appends text for mapped features (e.g. CDS feature for peptide or vice versa) + * Appends text for mapped features (e.g. CDS feature for peptide or vice + * versa) Returns number of features left if maxlength limit is (or would have + * been) reached. * * @param sb * @param residuePos * @param mf * @param fr + * @param maxlength */ - public void appendFeatures(StringBuilder sb, int residuePos, - MappedFeatures mf, FeatureRendererModel fr) + public int appendFeatures(StringBuilder sb, int residuePos, + MappedFeatures mf, FeatureRendererModel fr, int maxlength) { - for (SequenceFeature feature : mf.features) + for (int i = 0; i < mf.features.size(); i++) { - appendFeature(sb, residuePos, fr, feature, mf); + SequenceFeature feature = mf.features.get(i); + if (appendFeature(sb, residuePos, fr, feature, mf, maxlength)) + { + return mf.features.size() - i; + } } + return 0; } /** @@ -167,27 +197,58 @@ public class SequenceAnnotationReport * @param minmax * @param feature */ - void appendFeature(final StringBuilder sb, int rpos, + boolean appendFeature(final StringBuilder sb0, int rpos, FeatureRendererModel fr, SequenceFeature feature, - MappedFeatures mf) + MappedFeatures mf, int maxlength) { + int begin = feature.getBegin(); + int end = feature.getEnd(); + + /* + * if this is a virtual features, convert begin/end to the + * coordinates of the sequence it is mapped to + */ + int[] beginRange = null; + int[] endRange = null; + if (mf != null) + { + beginRange = mf.getMappedPositions(begin, begin); + endRange = mf.getMappedPositions(end, end); + if (beginRange == null || endRange == null) + { + // something went wrong + return false; + } + begin = beginRange[0]; + end = endRange[endRange.length - 1]; + } + + StringBuilder sb = new StringBuilder(); if (feature.isContactFeature()) { - if (feature.getBegin() == rpos || feature.getEnd() == rpos) + /* + * include if rpos is at start or end position of [mapped] feature + */ + boolean showContact = (mf == null) && (rpos == begin || rpos == end); + boolean showMappedContact = (mf != null) && ((rpos >= beginRange[0] + && rpos <= beginRange[beginRange.length - 1]) + || (rpos >= endRange[0] + && rpos <= endRange[endRange.length - 1])); + if (showContact || showMappedContact) { - if (sb.length() > 6) + if (sb0.length() > 6) { - sb.append("
"); + sb.append("
"); } - sb.append(feature.getType()).append(" ").append(feature.getBegin()) - .append(":").append(feature.getEnd()); + sb.append(feature.getType()).append(" ").append(begin).append(":") + .append(end); } - return; + return appendText(sb0, sb, maxlength); } - if (sb.length() > 6) + if (sb0.length() > 6) { - sb.append("
"); + sb.append("
"); } // TODO: remove this hack to display link only features boolean linkOnly = feature.getValue("linkonly") != null; @@ -197,11 +258,11 @@ public class SequenceAnnotationReport 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(begin); + if (begin != end) + { + sb.append(" ").append(end); + } } String description = feature.getDescription(); @@ -211,14 +272,17 @@ public class SequenceAnnotationReport /* * truncate overlong descriptions unless they contain an href - * (as truncation could leave corrupted html) + * before the truncation point (as truncation could leave corrupted html) */ - boolean hasLink = description.indexOf("a href") > -1; + int linkindex = description.toLowerCase().indexOf(" -1 + && linkindex < MAX_DESCRIPTION_LENGTH; if (description.length() > MAX_DESCRIPTION_LENGTH && !hasLink) { description = description.substring(0, MAX_DESCRIPTION_LENGTH) + ELLIPSIS; } + sb.append("; ").append(description); } @@ -259,6 +323,28 @@ public class SequenceAnnotationReport } } } + return appendText(sb0, sb, maxlength); + } + + /** + * Appends sb to sb0, and returns false, unless maxlength is not zero and + * appending would make the result longer than or equal to maxlength, in which + * case the append is not done and returns true + * + * @param sb0 + * @param sb + * @param maxlength + * @return + */ + private static boolean appendText(StringBuilder sb0, StringBuilder sb, + int maxlength) + { + if (maxlength == 0 || sb0.length() + sb.length() < maxlength) + { + sb0.append(sb); + return false; + } + return true; } /** @@ -318,7 +404,8 @@ 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) { @@ -392,12 +479,27 @@ public class SequenceAnnotationReport sb.append(tmp); maxWidth = Math.max(maxWidth, tmp.length()); } + SequenceI ds = sequence; while (ds.getDatasetSequence() != null) { ds = ds.getDatasetSequence(); } + /* + * add any annotation scores + */ + AlignmentAnnotation[] anns = ds.getAnnotation(); + for (int i = 0; anns != null && i < anns.length; i++) + { + AlignmentAnnotation aa = anns[i]; + if (aa != null && aa.hasScore() && aa.sequenceRef != null) + { + sb.append("
").append(aa.label).append(": ") + .append(aa.getScore()); + } + } + if (showDbRefs) { maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary)); @@ -412,12 +514,29 @@ public class SequenceAnnotationReport .getNonPositionalFeatures()) { int sz = -sb.length(); - appendFeature(sb, 0, fr, sf, null); + appendFeature(sb, 0, fr, sf, null, 0); sz += sb.length(); maxWidth = Math.max(maxWidth, sz); } } + + + if (sequence.getAnnotation("Search Scores") != null) + { + sb.append("
"); + String eValue = " E-Value: " + + sequence.getAnnotation("Search Scores")[0].getEValue(); + String bitScore = " Bit Score: " + + sequence.getAnnotation("Search Scores")[0].getBitScore(); + sb.append(eValue); + sb.append("
"); + sb.append(bitScore); + maxWidth = Math.max(maxWidth, eValue.length()); + maxWidth = Math.max(maxWidth, bitScore.length()); + } + sb.append("
"); sb.append(""); + return maxWidth; } @@ -433,14 +552,14 @@ public class SequenceAnnotationReport protected int appendDbRefs(final StringBuilder sb, SequenceI ds, boolean summary) { - DBRefEntry[] dbrefs = ds.getDBRefs(); + List dbrefs = ds.getDBRefs(); if (dbrefs == null) { return 0; } // note this sorts the refs held on the sequence! - Arrays.sort(dbrefs, comparator); + dbrefs.sort(comparator); boolean ellipsis = false; String source = null; String lastSource = null; @@ -475,7 +594,7 @@ public class SequenceAnnotationReport countForSource++; if (countForSource == 1 || !summary) { - sb.append("
"); + sb.append("
"); } if (countForSource <= MAX_REFS_PER_SOURCE || !summary) { @@ -501,11 +620,11 @@ public class SequenceAnnotationReport } if (moreSources) { - sb.append("
").append(source).append(COMMA).append(ELLIPSIS); + sb.append("
").append(source).append(COMMA).append(ELLIPSIS); } if (ellipsis) { - sb.append("
("); + sb.append("
("); sb.append(MessageManager.getString("label.output_seq_details")); sb.append(")"); }