/**
* Answers the mapped ranges (as one or more [start, end] positions) which
- * correspond to the given [begin, end] range of the linked sequence.
+ * correspond to the given [begin, end] range of (some feature on) the linked
+ * sequence.
*
* <pre>
* Example: MappedFeatures with CDS features mapped to peptide
*/
public int[] getMappedPositions(int begin, int end)
{
+ int[] result = null;
MapList map = mapping.getMap();
- return mapping.to == featureSequence ? map.locateInFrom(begin, end)
- : map.locateInTo(begin, end);
+ if (mapping.to == featureSequence)
+ {
+ result = map.locateInFrom(begin, end);
+ if (result == null)
+ {
+ // fudge for feature (e.g. CDS) extending to a mapped stop codon
+ result = map.locateInFrom(begin, end-3);
+ }
+ }
+ else
+ {
+ result = map.locateInTo(begin, end);
+ if (result == null)
+ {
+ // fudge for feature (e.g. CDS) extending to a mapped stop codon
+ result = map.locateInTo(begin, end-3);
+ }
+ }
+ return result;
}
/**
String consequence = "";
if (mf != null)
{
- int[] beginRange = mf.getMappedPositions(begin, begin);
- int[] endRange = mf.getMappedPositions(end, end);
- int from = beginRange[0];
- int to = endRange[endRange.length - 1];
+ 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));
/*
* show local rather than linked feature coordinates
*/
- int[] beginRange = mf.getMappedPositions(start, start);
- start = beginRange[0];
- int[] endRange = mf.getMappedPositions(end, end);
- end = endRange[endRange.length - 1];
+ int[] localRange = mf.getMappedPositions(start, end);
+ start = localRange[0];
+ end = localRange[localRange.length - 1];
}
StringBuilder desc = new StringBuilder();
desc.append(sf.getType()).append(" ").append(String.valueOf(start));
}
};
- private boolean forTooltip;
-
/**
- * Constructor given a flag which affects behaviour
- * <ul>
- * <li>if true, generates feature details suitable to show in a tooltip</li>
- * <li>if false, generates feature details in a form suitable for the sequence
- * details report</li>
- * </ul>
- *
- * @param isForTooltip
+ * Constructor
*/
public SequenceAnnotationReport(boolean isForTooltip)
{
- this.forTooltip = isForTooltip;
if (linkImageURL == null)
{
linkImageURL = getClass().getResource("/images/link.gif").toString();
* 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;
+ int[] localRange = null;
if (mf != null)
{
- beginRange = mf.getMappedPositions(begin, begin);
- endRange = mf.getMappedPositions(end, end);
- if (beginRange == null || endRange == null)
+ localRange = mf.getMappedPositions(begin, end);
+ if (localRange == null)
{
// something went wrong
return false;
}
- begin = beginRange[0];
- end = endRange[endRange.length - 1];
+ begin = localRange[0];
+ end = localRange[localRange.length - 1];
}
StringBuilder sb = new StringBuilder();
if (feature.isContactFeature())
{
/*
- * include if rpos is at start or end position of [mapped] feature
+ * contact features are rendered slightly differently; note the check for
+ * 'start or end position only' was applied earlier when finding features
*/
- 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 (sb0.length() > 6)
{
- if (sb0.length() > 6)
- {
- sb.append("<br/>");
- }
- sb.append(feature.getType()).append(" ").append(begin).append(":")
- .append(end);
+ sb.append("<br/>");
}
+ sb.append(feature.getType()).append(" ").append(begin).append(":")
+ .append(end);
return appendText(sb0, sb, maxlength);
}
import static org.testng.Assert.assertEquals;
-import jalview.util.MapList;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import org.testng.annotations.Test;
+import jalview.util.MapList;
+
public class MappedFeaturesTest
{
@Test(groups = "Functional")
* dna/10-20 aCGTaGctGAa (codons CGT=R, GGA = G)
* mapping: 3:1 from [11-13,15,18-19] to peptide/1-2 RG
*/
- SequenceI from = new Sequence("dna/10-20", "acgTAGCTGAA");
+ SequenceI from = new Sequence("dna/10-20", "aCGTaGctGAa");
SequenceI to = new Sequence("peptide", "RG");
MapList map = new MapList(new int[] { 11, 13, 15, 15, 18, 19 },
new int[]
variant = mf.findProteinVariants(sf9);
assertEquals(variant, "");
}
+
+ @Test(groups = "Functional")
+ public void testGetMappedPositions()
+ {
+ // CDS including stop codon taa
+ SequenceI cds = new Sequence("cds/10-21", "ATGcgtGGAtaa");
+ SequenceI peptide = new Sequence("peptide", "MRG"); // ATG, CGT, GGA
+
+ /*
+ * emulate 'map from' range based on CDS _including_ stop codon
+ */
+ MapList map = new MapList(new int[] { 10, 21 }, new int[] { 1, 3 }, 3,
+ 1);
+ Mapping mapping = new Mapping(peptide, map);
+
+ MappedFeatures mf = new MappedFeatures(mapping, cds, 2, 'M', null);
+
+ /*
+ * scenario: sequence_variant feature on CDS at position 14;
+ * find the corresponding position on peptide
+ */
+ int[] pepPos = mf.getMappedPositions(14, 14);
+ assertEquals(pepPos[0], 2);
+ assertEquals(pepPos[1], 2);
+
+ /*
+ * scenario: exon feature on CDS including stop codon;
+ */
+ pepPos = mf.getMappedPositions(10, 21);
+ assertEquals(pepPos[0], 1);
+ assertEquals(pepPos[1], 3);
+
+ /*
+ * now with the mapping from protein to CDS
+ */
+ mapping = new Mapping(cds, map.getInverse());
+ mf = new MappedFeatures(mapping, peptide, 15, 't', null);
+ int[] cdsPos = mf.getMappedPositions(2, 2);
+ assertEquals(cdsPos[0], 13);
+ assertEquals(cdsPos[1], 15);
+ }
}
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(false);
StringBuilder sb = new StringBuilder();
- sb.append("123456");
+ sb.append("foo ");
SequenceFeature sf = new SequenceFeature("disulfide bond", "desc", 1,
3, 1.2f, "group");
- // residuePos == 2 does not match start or end of feature, nothing done:
- sar.appendFeature(sb, 2, null, sf, null, 0);
- assertEquals("123456", sb.toString());
-
// residuePos == 1 matches start of feature, text appended (but no <br/>)
// feature score is not included
sar.appendFeature(sb, 1, null, sf, null, 0);
- assertEquals("123456disulfide bond 1:3", sb.toString());
+ assertEquals("foo disulfide bond 1:3", sb.toString());
- // residuePos == 3 matches end of feature, text appended
+ // residuePos == 2 doesnt' match end of feature, text appended anyway
+ // (the test for this is handled by FeatureStore.findContactFeatures())
// <br/> is prefixed once sb.length() > 6
- sar.appendFeature(sb, 3, null, sf, null, 0);
- assertEquals("123456disulfide bond 1:3<br/>disulfide bond 1:3",
+ sar.appendFeature(sb, 2, null, sf, null, 0);
+ assertEquals("foo disulfide bond 1:3<br/>disulfide bond 1:3",
sb.toString());
}