X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Fjalview%2Fdatamodel%2FSequenceFeature.java;h=1f498b94abbd5eb688cad365c98a7af9c52eda96;hb=d1e20f6a5654ea6baf378afa3277b4e751c69a96;hp=e7e1342e67605e73f709343d9af54125e0050893;hpb=4eb8d7a0f14e5dd1dc5ad5ad0960bae9b25fa043;p=jalview.git diff --git a/src/jalview/datamodel/SequenceFeature.java b/src/jalview/datamodel/SequenceFeature.java index e7e1342..1f498b9 100755 --- a/src/jalview/datamodel/SequenceFeature.java +++ b/src/jalview/datamodel/SequenceFeature.java @@ -20,21 +20,21 @@ */ package jalview.datamodel; -import jalview.datamodel.features.FeatureAttributeType; -import jalview.datamodel.features.FeatureAttributes; -import jalview.datamodel.features.FeatureLocationI; -import jalview.datamodel.features.FeatureSourceI; -import jalview.datamodel.features.FeatureSources; -import jalview.util.StringUtils; - import java.util.Comparator; -import java.util.HashMap; +import java.util.LinkedHashMap; import java.util.Map; import java.util.Map.Entry; import java.util.SortedMap; import java.util.TreeMap; import java.util.Vector; +import jalview.datamodel.features.FeatureAttributeType; +import jalview.datamodel.features.FeatureAttributes; +import jalview.datamodel.features.FeatureLocationI; +import jalview.datamodel.features.FeatureSourceI; +import jalview.datamodel.features.FeatureSources; +import jalview.util.StringUtils; + /** * A class that models a single contiguous feature on a sequence. If flag * 'contactFeature' is true, the start and end positions are interpreted instead @@ -50,10 +50,10 @@ public class SequenceFeature implements FeatureLocationI private static final String STATUS = "status"; - private static final String STRAND = "STRAND"; + public static final String STRAND = "STRAND"; - // private key for Phase designed not to conflict with real GFF data - private static final String PHASE = "!Phase"; + // key for Phase designed not to conflict with real GFF data + public static final String PHASE = "!Phase"; // private key for ENA location designed not to conflict with real GFF data private static final String LOCATION = "!Location"; @@ -61,12 +61,6 @@ public class SequenceFeature implements FeatureLocationI private static final String ROW_DATA = "%s%s%s"; /* - * ATTRIBUTES is reserved for the GFF 'column 9' data, formatted as - * name1=value1;name2=value2,value3;...etc - */ - private static final String ATTRIBUTES = "ATTRIBUTES"; - - /* * type, begin, end, featureGroup, score and contactFeature are final * to ensure that the integrity of SequenceFeatures data store * can't be broken by direct update of these fields @@ -108,8 +102,8 @@ public class SequenceFeature implements FeatureLocationI */ public SequenceFeature(SequenceFeature cpy) { - this(cpy, cpy.getBegin(), cpy.getEnd(), cpy.getFeatureGroup(), cpy - .getScore()); + this(cpy, cpy.getBegin(), cpy.getEnd(), cpy.getFeatureGroup(), + cpy.getScore()); } /** @@ -174,19 +168,13 @@ public class SequenceFeature implements FeatureLocationI if (sf.otherDetails != null) { - otherDetails = new HashMap<>(); - for (Entry entry : sf.otherDetails.entrySet()) - { - otherDetails.put(entry.getKey(), entry.getValue()); - } + otherDetails = new LinkedHashMap<>(); + otherDetails.putAll(sf.otherDetails); } if (sf.links != null && sf.links.size() > 0) { links = new Vector<>(); - for (int i = 0, iSize = sf.links.size(); i < iSize; i++) - { - links.addElement(sf.links.elementAt(i)); - } + links.addAll(sf.links); } } @@ -389,10 +377,10 @@ public class SequenceFeature implements FeatureLocationI /** * Answers the value of the specified attribute as string, or null if no such - * value. If more than one attribute name is provided, tries to resolve as keys - * to nested maps. For example, if attribute "CSQ" holds a map of key-value - * pairs, then getValueAsString("CSQ", "Allele") returns the value of "Allele" - * in that map. + * value. If more than one attribute name is provided, tries to resolve as + * keys to nested maps. For example, if attribute "CSQ" holds a map of + * key-value pairs, then getValueAsString("CSQ", "Allele") returns the value + * of "Allele" in that map. * * @param key * @return @@ -440,7 +428,10 @@ public class SequenceFeature implements FeatureLocationI { if (otherDetails == null) { - otherDetails = new HashMap<>(); + /* + * LinkedHashMap preserves insertion order of attributes + */ + otherDetails = new LinkedHashMap<>(); } otherDetails.put(key, value); @@ -483,16 +474,6 @@ public class SequenceFeature implements FeatureLocationI return (String) getValue(STATUS); } - public void setAttributes(String attr) - { - setValue(ATTRIBUTES, attr); - } - - public String getAttributes() - { - return (String) getValue(ATTRIBUTES); - } - /** * Return 1 for forward strand ('+' in GFF), -1 for reverse strand ('-' in * GFF), and 0 for unknown or not (validly) specified @@ -605,13 +586,17 @@ public class SequenceFeature implements FeatureLocationI } /** - * Answers an html-formatted report of feature details + * Answers an html-formatted report of feature details. If parameter + * {@code mf} is not null, the feature is a virtual linked feature, and + * details included both the original location and the mapped location + * (CDS/peptide). * - * @param sequence + * @param seqName + * @param mf * * @return */ - public String getDetailsReport(SequenceI sequence) + public String getDetailsReport(String seqName, MappedFeatures mf) { FeatureSourceI metadata = FeatureSources.getInstance() .getSource(source); @@ -619,9 +604,24 @@ public class SequenceFeature implements FeatureLocationI StringBuilder sb = new StringBuilder(128); sb.append("
"); sb.append(""); - sb.append(String.format(ROW_DATA, "Location", sequence.getName(), - begin == end ? begin - : begin + (isContactFeature() ? ":" : "-") + end)); + String name = mf == null ? seqName : mf.getLinkedSequenceName(); + sb.append(String.format(ROW_DATA, "Location", name, begin == end ? begin + : begin + (isContactFeature() ? ":" : "-") + end)); + + String consequence = ""; + if (mf != null) + { + int[] localRange = mf.getMappedPositions(begin, end); + int from = localRange[0]; + int to = localRange[localRange.length - 1]; + String s = mf.isFromCds() ? "Peptide Location" : "Coding location"; + sb.append(String.format(ROW_DATA, s, seqName, from == to ? from + : from + (isContactFeature() ? ":" : "-") + to)); + if (mf.isFromCds()) + { + consequence = mf.findProteinVariants(this); + } + } sb.append(String.format(ROW_DATA, "Type", type, "")); String desc = StringUtils.stripHtmlTags(description); sb.append(String.format(ROW_DATA, "Description", desc, "")); @@ -634,6 +634,12 @@ public class SequenceFeature implements FeatureLocationI sb.append(String.format(ROW_DATA, "Group", featureGroup, "")); } + if (!consequence.isEmpty()) + { + sb.append(String.format(ROW_DATA, "Consequence", + "Translated by Jalview", consequence)); + } + if (otherDetails != null) { TreeMap ordered = new TreeMap<>( @@ -643,10 +649,6 @@ public class SequenceFeature implements FeatureLocationI for (Entry entry : ordered.entrySet()) { String key = entry.getKey(); - if (ATTRIBUTES.equals(key)) - { - continue; // to avoid double reporting - } Object value = entry.getValue(); if (value instanceof Map) @@ -661,8 +663,8 @@ public class SequenceFeature implements FeatureLocationI sm.putAll(values); for (Entry e : sm.entrySet()) { - sb.append(String.format(ROW_DATA, key, e.getKey().toString(), e - .getValue().toString())); + sb.append(String.format(ROW_DATA, key, e.getKey().toString(), + e.getValue().toString())); } } else @@ -676,8 +678,8 @@ public class SequenceFeature implements FeatureLocationI String s = entry.getValue().toString(); if (isValueInteresting(key, s, metadata)) { - sb.append(String.format(ROW_DATA, key, attDesc == null ? "" - : attDesc, s)); + sb.append(String.format(ROW_DATA, key, + attDesc == null ? "" : attDesc, s)); } } } @@ -715,9 +717,8 @@ public class SequenceFeature implements FeatureLocationI } FeatureAttributeType attType = metadata.getAttributeType(key); - if (attType != null - && (attType == FeatureAttributeType.Float || attType - .equals(FeatureAttributeType.Integer))) + if (attType != null && (attType == FeatureAttributeType.Float + || attType.equals(FeatureAttributeType.Integer))) { try {