From c6018dc0dc12720e13b75850a5303279ac7094b7 Mon Sep 17 00:00:00 2001 From: gmungoc Date: Thu, 27 Aug 2020 16:02:06 +0100 Subject: [PATCH] JAL-3725 restrict mapped virtual feature location to mapped region Conflicts: src/jalview/gui/PopupMenu.java --- src/jalview/datamodel/MappedFeatures.java | 4 +- src/jalview/datamodel/SequenceFeature.java | 7 ++- src/jalview/gui/PopupMenu.java | 7 +++ src/jalview/io/SequenceAnnotationReport.java | 23 +++++++-- test/jalview/datamodel/SequenceFeatureTest.java | 59 +++++++++++++++-------- 5 files changed, 69 insertions(+), 31 deletions(-) diff --git a/src/jalview/datamodel/MappedFeatures.java b/src/jalview/datamodel/MappedFeatures.java index d652a97..57c8c37 100644 --- a/src/jalview/datamodel/MappedFeatures.java +++ b/src/jalview/datamodel/MappedFeatures.java @@ -294,8 +294,8 @@ public class MappedFeatures public int[] getMappedPositions(int begin, int end) { MapList map = mapping.getMap(); - return mapping.to == featureSequence ? map.locateInFrom(begin, end) - : map.locateInTo(begin, end); + return mapping.to == featureSequence ? map.getOverlapsInFrom(begin, end) + : map.getOverlapsInTo(begin, end); } /** diff --git a/src/jalview/datamodel/SequenceFeature.java b/src/jalview/datamodel/SequenceFeature.java index 6eeba2f..bbf1b45 100755 --- a/src/jalview/datamodel/SequenceFeature.java +++ b/src/jalview/datamodel/SequenceFeature.java @@ -612,10 +612,9 @@ public class SequenceFeature implements FeatureLocationI 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)); diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java index fc3c342..abe9835 100644 --- a/src/jalview/gui/PopupMenu.java +++ b/src/jalview/gui/PopupMenu.java @@ -840,6 +840,13 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener } start = beginRange[0]; end = endRange[endRange.length - 1]; + int[] localRange = mf.getMappedPositions(start, end); + if (localRange == null) + { + return; + } + start = localRange[0]; + end = localRange[localRange.length - 1]; } StringBuilder desc = new StringBuilder(); desc.append(sf.getType()).append(" ").append(String.valueOf(start)); diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java index 27c1652..a4c4895 100644 --- a/src/jalview/io/SequenceAnnotationReport.java +++ b/src/jalview/io/SequenceAnnotationReport.java @@ -210,12 +210,27 @@ public class SequenceAnnotationReport * 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[] beginRange = null; // feature start in local coordinates + int[] endRange = null; // feature end in local coordinates if (mf != null) { - beginRange = mf.getMappedPositions(begin, begin); - endRange = mf.getMappedPositions(end, end); + if (feature.isContactFeature()) + { + /* + * map start and end points individually + */ + beginRange = mf.getMappedPositions(begin, begin); + endRange = begin == end ? beginRange + : mf.getMappedPositions(end, end); + } + else + { + /* + * map the feature extent + */ + beginRange = mf.getMappedPositions(begin, end); + endRange = beginRange; + } if (beginRange == null || endRange == null) { // something went wrong diff --git a/test/jalview/datamodel/SequenceFeatureTest.java b/test/jalview/datamodel/SequenceFeatureTest.java index f8479a3..bd5e9ac 100644 --- a/test/jalview/datamodel/SequenceFeatureTest.java +++ b/test/jalview/datamodel/SequenceFeatureTest.java @@ -48,8 +48,8 @@ public class SequenceFeatureTest @Test(groups = { "Functional" }) public void testCopyConstructors() { - SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, - 12.5f, "group"); + SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, 12.5f, + "group"); sf1.setValue("STRAND", "+"); sf1.setValue("Note", "Testing"); Integer count = Integer.valueOf(7); @@ -83,8 +83,8 @@ public class SequenceFeatureTest /* * copy constructor modifying type/begin/end/group/score */ - SequenceFeature sf4 = new SequenceFeature(sf1, "Disulfide bond", 12, - 15, "group3", -9.1f); + SequenceFeature sf4 = new SequenceFeature(sf1, "Disulfide bond", 12, 15, + "group3", -9.1f); assertEquals("Disulfide bond", sf4.getType()); assertTrue(sf4.isContactFeature()); assertEquals("desc", sf4.getDescription()); @@ -104,8 +104,8 @@ public class SequenceFeatureTest @Test(groups = { "Functional" }) public void testGetValue() { - SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, - 12.5f, "group"); + SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, 12.5f, + "group"); sf1.setValue("STRAND", "+"); assertEquals("+", sf1.getValue("STRAND")); assertNull(sf1.getValue("strand")); // case-sensitive @@ -137,15 +137,15 @@ public class SequenceFeatureTest @Test(groups = { "Functional" }) public void testEqualsAndHashCode() { - SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, - 12.5f, "group"); + SequenceFeature sf1 = new SequenceFeature("type", "desc", 22, 33, 12.5f, + "group"); sf1.setValue("ID", "id"); sf1.setValue("Name", "name"); sf1.setValue("Parent", "parent"); sf1.setStrand("+"); sf1.setPhase("1"); - SequenceFeature sf2 = new SequenceFeature("type", "desc", 22, 33, - 12.5f, "group"); + SequenceFeature sf2 = new SequenceFeature("type", "desc", 22, 33, 12.5f, + "group"); sf2.setValue("ID", "id"); sf2.setValue("Name", "name"); sf2.setValue("Parent", "parent"); @@ -158,10 +158,10 @@ public class SequenceFeatureTest assertEquals(sf1.hashCode(), sf2.hashCode()); // changing type breaks equals: - SequenceFeature sf3 = new SequenceFeature("type", "desc", 22, 33, - 12.5f, "group"); - SequenceFeature sf4 = new SequenceFeature("Type", "desc", 22, 33, - 12.5f, "group"); + SequenceFeature sf3 = new SequenceFeature("type", "desc", 22, 33, 12.5f, + "group"); + SequenceFeature sf4 = new SequenceFeature("Type", "desc", 22, 33, 12.5f, + "group"); assertFalse(sf3.equals(sf4)); // changing description breaks equals: @@ -195,7 +195,8 @@ public class SequenceFeatureTest // changing start position breaks equals: int restorei = sf2.getBegin(); - sf2 = new SequenceFeature(sf2, 21, sf2.getEnd(), sf2.getFeatureGroup(), sf2.getScore()); + sf2 = new SequenceFeature(sf2, 21, sf2.getEnd(), sf2.getFeatureGroup(), + sf2.getScore()); assertFalse(sf1.equals(sf2)); sf2 = new SequenceFeature(sf2, restorei, sf2.getEnd(), sf2.getFeatureGroup(), sf2.getScore()); @@ -210,9 +211,11 @@ public class SequenceFeatureTest // changing feature group breaks equals: restores = sf2.getFeatureGroup(); - sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), "Group", sf2.getScore()); + sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), "Group", + sf2.getScore()); assertFalse(sf1.equals(sf2)); - sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), restores, sf2.getScore()); + sf2 = new SequenceFeature(sf2, sf2.getBegin(), sf2.getEnd(), restores, + sf2.getScore()); // changing ID breaks equals: restores = (String) sf2.getValue("ID"); @@ -285,7 +288,8 @@ public class SequenceFeatureTest String seqName = seq.getName(); // single locus, no group, no score - SequenceFeature sf = new SequenceFeature("variant", "G,C", 22, 22, null); + SequenceFeature sf = new SequenceFeature("variant", "G,C", 22, 22, + null); String expected = "
" + "" + "
LocationTestSeq22
Typevariant
DescriptionG,C
"; @@ -299,8 +303,7 @@ public class SequenceFeatureTest + "Descriptiona description"; assertEquals(expected, sf.getDetailsReport(seqName, null)); - sf = new SequenceFeature("variant", "G,C", 22, 33, - 12.5f, "group"); + sf = new SequenceFeature("variant", "G,C", 22, 33, 12.5f, "group"); sf.setValue("Parent", "ENSG001"); sf.setValue("Child", "ENSP002"); expected = "
" @@ -351,9 +354,23 @@ public class SequenceFeatureTest + "" + "" + "" - + "" + + "" + "
LocationTestSeq22-33
Typevariant
DescriptionG,C
ConsequenceTranslated by Jalviewp.Leu9Phe
allelesG,C
allelesG,C
"; assertEquals(expected, sf.getDetailsReport(seq.getName(), mf)); + + + /* + * exon feature extending beyond mapped range; mapped location should be + * restricted to peptide mapped range limit i.e. 10-13 + */ + SequenceFeature sf2 = new SequenceFeature("exon", "exon 1", 109, 230, null); + features.add(sf2); + expected = "
" + + "" + + "" + + "" + + "
LocationCds109-230
Peptide LocationTestSeq10-13
Typeexon
Descriptionexon 1
"; + assertEquals(expected, sf2.getDetailsReport(seq.getName(), mf)); } } -- 1.7.10.2