From: gmungoc
Date: Mon, 6 Nov 2017 16:41:54 +0000 (+0000)
Subject: JAL-2820 include attribute value used for feature colour in tooltip
X-Git-Tag: Release_2_11_0~152
X-Git-Url: http://source.jalview.org/gitweb/?a=commitdiff_plain;h=81c8008cff0d9a265e0fbe979b17b173e9e4fc0a;p=jalview.git
JAL-2820 include attribute value used for feature colour in tooltip
---
diff --git a/src/jalview/appletgui/APopupMenu.java b/src/jalview/appletgui/APopupMenu.java
index 46bd4fd..76f2705 100644
--- a/src/jalview/appletgui/APopupMenu.java
+++ b/src/jalview/appletgui/APopupMenu.java
@@ -901,10 +901,7 @@ public class APopupMenu extends java.awt.PopupMenu
.formatMessage("label.annotation_for_displayid", new Object[]
{ seq.getDisplayId(true) }));
new SequenceAnnotationReport(null).createSequenceAnnotationReport(
- contents, seq, true, true,
- (ap.seqPanel.seqCanvas.fr != null)
- ? ap.seqPanel.seqCanvas.fr.getMinMax()
- : null);
+ contents, seq, true, true, ap.seqPanel.seqCanvas.fr);
contents.append("
");
}
Frame frame = new Frame();
diff --git a/src/jalview/gui/IdPanel.java b/src/jalview/gui/IdPanel.java
index a4f79c2..a1726f1 100755
--- a/src/jalview/gui/IdPanel.java
+++ b/src/jalview/gui/IdPanel.java
@@ -108,8 +108,7 @@ public class IdPanel extends JPanel
SequenceI sequence = av.getAlignment().getSequenceAt(seq);
StringBuilder tip = new StringBuilder(64);
seqAnnotReport.createTooltipAnnotationReport(tip, sequence,
- av.isShowDBRefs(), av.isShowNPFeats(),
- sp.seqCanvas.fr.getMinMax());
+ av.isShowDBRefs(), av.isShowNPFeats(), sp.seqCanvas.fr);
setToolTipText(JvSwingUtils.wrapTooltip(true,
sequence.getDisplayId(true) + " " + tip.toString()));
}
diff --git a/src/jalview/gui/PopupMenu.java b/src/jalview/gui/PopupMenu.java
index 6da7d4f..97d051b 100644
--- a/src/jalview/gui/PopupMenu.java
+++ b/src/jalview/gui/PopupMenu.java
@@ -1635,10 +1635,7 @@ public class PopupMenu extends JPopupMenu implements ColourChangeListener
new Object[]
{ seq.getDisplayId(true) }) + "");
new SequenceAnnotationReport(null).createSequenceAnnotationReport(
- contents, seq, true, true,
- (ap.getSeqPanel().seqCanvas.fr != null)
- ? ap.getSeqPanel().seqCanvas.fr.getMinMax()
- : null);
+ contents, seq, true, true, ap.getSeqPanel().seqCanvas.fr);
contents.append("
");
}
cap.setText("" + contents.toString() + "");
diff --git a/src/jalview/gui/SeqPanel.java b/src/jalview/gui/SeqPanel.java
index 6148a2e..b718783 100644
--- a/src/jalview/gui/SeqPanel.java
+++ b/src/jalview/gui/SeqPanel.java
@@ -147,35 +147,33 @@ public class SeqPanel extends JPanel
SearchResultsI lastSearchResults;
/**
- * Creates a new SeqPanel object.
+ * Creates a new SeqPanel object
*
- * @param avp
- * DOCUMENT ME!
- * @param p
- * DOCUMENT ME!
+ * @param viewport
+ * @param alignPanel
*/
- public SeqPanel(AlignViewport av, AlignmentPanel ap)
+ public SeqPanel(AlignViewport viewport, AlignmentPanel alignPanel)
{
linkImageURL = getClass().getResource("/images/link.gif");
seqARep = new SequenceAnnotationReport(linkImageURL.toString());
ToolTipManager.sharedInstance().registerComponent(this);
ToolTipManager.sharedInstance().setInitialDelay(0);
ToolTipManager.sharedInstance().setDismissDelay(10000);
- this.av = av;
+ this.av = viewport;
setBackground(Color.white);
- seqCanvas = new SeqCanvas(ap);
+ seqCanvas = new SeqCanvas(alignPanel);
setLayout(new BorderLayout());
add(seqCanvas, BorderLayout.CENTER);
- this.ap = ap;
+ this.ap = alignPanel;
- if (!av.isDataset())
+ if (!viewport.isDataset())
{
addMouseMotionListener(this);
addMouseListener(this);
addMouseWheelListener(this);
- ssm = av.getStructureSelectionManager();
+ ssm = viewport.getStructureSelectionManager();
ssm.addStructureViewerListener(this);
ssm.addSelectionListener(this);
}
@@ -804,7 +802,7 @@ public class SeqPanel extends JPanel
List features = ap.getFeatureRenderer()
.findFeaturesAtColumn(sequence, column + 1);
seqARep.appendFeatures(tooltipText, pos, features,
- this.ap.getSeqPanel().seqCanvas.fr.getMinMax());
+ this.ap.getSeqPanel().seqCanvas.fr);
}
if (tooltipText.length() == 6) //
{
diff --git a/src/jalview/io/SequenceAnnotationReport.java b/src/jalview/io/SequenceAnnotationReport.java
index 6d819d3..1f92428 100644
--- a/src/jalview/io/SequenceAnnotationReport.java
+++ b/src/jalview/io/SequenceAnnotationReport.java
@@ -20,14 +20,15 @@
*/
package jalview.io;
+import jalview.api.FeatureColourI;
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;
@@ -87,14 +88,14 @@ public class SequenceAnnotationReport
{
return 1;
}
- int comp = s1 == null ? -1
- : (s2 == null ? 1 : s1.compareToIgnoreCase(s2));
+ int comp = s1 == null ? -1 : (s2 == null ? 1 : s1
+ .compareToIgnoreCase(s2));
if (comp == 0)
{
String a1 = ref1.getAccessionId();
String a2 = ref2.getAccessionId();
- comp = a1 == null ? -1
- : (a2 == null ? 1 : a1.compareToIgnoreCase(a2));
+ comp = a1 == null ? -1 : (a2 == null ? 1 : a1
+ .compareToIgnoreCase(a2));
}
return comp;
}
@@ -115,9 +116,9 @@ public class SequenceAnnotationReport
}
};
- public SequenceAnnotationReport(String linkImageURL)
+ public SequenceAnnotationReport(String linkURL)
{
- this.linkImageURL = linkImageURL;
+ this.linkImageURL = linkURL;
}
/**
@@ -129,13 +130,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);
}
}
}
@@ -149,7 +150,7 @@ public class SequenceAnnotationReport
* @param feature
*/
void appendFeature(final StringBuilder sb, int rpos,
- Map minmax, SequenceFeature feature)
+ FeatureRendererModel fr, SequenceFeature feature)
{
if (feature.isContactFeature())
{
@@ -162,60 +163,91 @@ public class SequenceAnnotationReport
sb.append(feature.getType()).append(" ").append(feature.getBegin())
.append(":").append(feature.getEnd());
}
+ return;
}
- else
+
+ if (sb.length() > 6)
+ {
+ sb.append("
");
+ }
+ // 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);
+ }
- String description = feature.getDescription();
- if (description != null && !description.equals(feature.getType()))
- {
- description = StringUtils.stripHtmlTags(description);
- sb.append("; ").append(description);
- }
- // check score should be shown
- if (!Float.isNaN(feature.getScore()))
+ String description = feature.getDescription();
+ if (description != null && !description.equals(feature.getType()))
+ {
+ description = StringUtils.stripHtmlTags(description);
+ sb.append("; ").append(description);
+ }
+
+ 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(")");
+ }
+
+ /*
+ * 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
- : 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=").append(String.valueOf(feature.getScore()));
+ sb.append("; ").append(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
*
@@ -238,19 +270,20 @@ public class SequenceAnnotationReport
{
for (List urllink : createLinksFrom(null, urlstring))
{
- sb.append("
"
+ sb.append("
"
+ (urllink.get(0).toLowerCase()
- .equals(urllink.get(1).toLowerCase())
- ? urllink.get(0)
- : (urllink.get(0) + ":"
- + urllink.get(1)))
- + "");
+ .equals(urllink.get(1).toLowerCase()) ? urllink
+ .get(0) : (urllink.get(0) + ":" + urllink
+ .get(1))) + "");
}
} catch (Exception x)
{
- System.err.println(
- "problem when creating links from " + urlstring);
+ System.err.println("problem when creating links from "
+ + urlstring);
x.printStackTrace();
}
}
@@ -283,10 +316,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);
}
/**
@@ -301,13 +334,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("");
@@ -324,7 +357,7 @@ public class SequenceAnnotationReport
{
ds = ds.getDatasetSequence();
}
-
+
if (showDbRefs)
{
maxWidth = Math.max(maxWidth, appendDbRefs(sb, ds, summary));
@@ -339,7 +372,7 @@ public class SequenceAnnotationReport
.getNonPositionalFeatures())
{
int sz = -sb.length();
- appendFeature(sb, 0, minmax, sf);
+ appendFeature(sb, 0, fr, sf);
sz += sb.length();
maxWidth = Math.max(maxWidth, sz);
}
@@ -428,8 +461,7 @@ public class SequenceAnnotationReport
}
if (moreSources)
{
- sb.append("
").append(source)
- .append(COMMA).append(ELLIPSIS);
+ sb.append("
").append(source).append(COMMA).append(ELLIPSIS);
}
if (ellipsis)
{
@@ -443,10 +475,10 @@ public class SequenceAnnotationReport
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);
+ int maxWidth = createSequenceAnnotationReport(tip, sequence,
+ showDbRefs, showNpFeats, fr, true);
if (maxWidth > 60)
{
diff --git a/test/jalview/io/SequenceAnnotationReportTest.java b/test/jalview/io/SequenceAnnotationReportTest.java
index 9e61bec..87e35c7 100644
--- a/test/jalview/io/SequenceAnnotationReportTest.java
+++ b/test/jalview/io/SequenceAnnotationReportTest.java
@@ -23,15 +23,18 @@ package jalview.io;
import static org.testng.AssertJUnit.assertEquals;
import static org.testng.AssertJUnit.assertTrue;
+import jalview.api.FeatureColourI;
import jalview.datamodel.DBRefEntry;
import jalview.datamodel.Sequence;
import jalview.datamodel.SequenceFeature;
import jalview.datamodel.SequenceI;
import jalview.gui.JvOptionPane;
import jalview.io.gff.GffConstants;
+import jalview.renderer.seqfeatures.FeatureRenderer;
+import jalview.schemes.FeatureColour;
+import jalview.viewmodel.seqfeatures.FeatureRendererModel;
-import java.util.HashMap;
-import java.util.Hashtable;
+import java.awt.Color;
import java.util.Map;
import junit.extensions.PA;
@@ -95,8 +98,9 @@ public class SequenceAnnotationReportTest
SequenceFeature sf = new SequenceFeature("METAL", "Fe2-S", 1, 3, 1.3f,
"group");
- Map minmax = new Hashtable();
- sar.appendFeature(sb, 1, minmax, sf);
+ FeatureRendererModel fr = new FeatureRenderer(null);
+ Map minmax = fr.getMinMax();
+ sar.appendFeature(sb, 1, fr, sf);
/*
* map has no entry for this feature type - score is not shown:
*/
@@ -106,7 +110,7 @@ public class SequenceAnnotationReportTest
* map has entry for this feature type - score is shown:
*/
minmax.put("METAL", new float[][] { { 0f, 1f }, null });
- sar.appendFeature(sb, 1, minmax, sf);
+ sar.appendFeature(sb, 1, fr, sf);
//
is appended to a buffer > 6 in length
assertEquals("METAL 1 3; Fe2-S
METAL 1 3; Fe2-S Score=1.3",
sb.toString());
@@ -116,7 +120,7 @@ public class SequenceAnnotationReportTest
*/
minmax.put("METAL", new float[][] { { 2f, 2f }, null });
sb.setLength(0);
- sar.appendFeature(sb, 1, minmax, sf);
+ sar.appendFeature(sb, 1, fr, sf);
assertEquals("METAL 1 3; Fe2-S", sb.toString());
}
@@ -132,8 +136,11 @@ public class SequenceAnnotationReportTest
assertEquals("METAL 1 3; Fe2-S", sb.toString());
}
+ /**
+ * A specific attribute value is included if it is used to colour the feature
+ */
@Test(groups = "Functional")
- public void testAppendFeature_clinicalSignificance()
+ public void testAppendFeature_colouredByAttribute()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
StringBuilder sb = new StringBuilder();
@@ -141,12 +148,35 @@ public class SequenceAnnotationReportTest
Float.NaN, "group");
sf.setValue("clinical_significance", "Benign");
- sar.appendFeature(sb, 1, null, sf);
- assertEquals("METAL 1 3; Fe2-S; Benign", sb.toString());
+ /*
+ * first with no colour by attribute
+ */
+ FeatureRendererModel fr = new FeatureRenderer(null);
+ sar.appendFeature(sb, 1, fr, sf);
+ assertEquals("METAL 1 3; Fe2-S", sb.toString());
+
+ /*
+ * then with colour by an attribute the feature lacks
+ */
+ FeatureColourI fc = new FeatureColour(Color.white, Color.black, 5, 10);
+ fc.setAttributeName("Pfam");
+ fr.setColour("METAL", fc);
+ sb.setLength(0);
+ sar.appendFeature(sb, 1, fr, sf);
+ assertEquals("METAL 1 3; Fe2-S", sb.toString()); // no change
+
+ /*
+ * then with colour by an attribute the feature has
+ */
+ fc.setAttributeName("clinical_significance");
+ sb.setLength(0);
+ sar.appendFeature(sb, 1, fr, sf);
+ assertEquals("METAL 1 3; Fe2-S; clinical_significance=Benign",
+ sb.toString());
}
@Test(groups = "Functional")
- public void testAppendFeature_withScoreStatusClinicalSignificance()
+ public void testAppendFeature_withScoreStatusAttribute()
{
SequenceAnnotationReport sar = new SequenceAnnotationReport(null);
StringBuilder sb = new StringBuilder();
@@ -154,11 +184,17 @@ public class SequenceAnnotationReportTest
"group");
sf.setStatus("Confirmed");
sf.setValue("clinical_significance", "Benign");
- Map minmax = new Hashtable();
+
+ FeatureRendererModel fr = new FeatureRenderer(null);
+ Map minmax = fr.getMinMax();
+ FeatureColourI fc = new FeatureColour(Color.white, Color.blue, 12, 22);
+ fc.setAttributeName("clinical_significance");
+ fr.setColour("METAL", fc);
minmax.put("METAL", new float[][] { { 0f, 1f }, null });
- sar.appendFeature(sb, 1, minmax, sf);
+ sar.appendFeature(sb, 1, fr, sf);
- assertEquals("METAL 1 3; Fe2-S Score=1.3; (Confirmed); Benign",
+ assertEquals(
+ "METAL 1 3; Fe2-S Score=1.3; (Confirmed); clinical_significance=Benign",
sb.toString());
}
@@ -226,7 +262,7 @@ public class SequenceAnnotationReportTest
null));
sb.setLength(0);
sar.createSequenceAnnotationReport(sb, seq, true, true, null);
- String expected = "
SeqDesc
Type1 ; Nonpos";
+ String expected = "
SeqDesc
Type1 ; Nonpos Score=1.0";
assertEquals(expected, sb.toString());
/*
@@ -244,10 +280,13 @@ public class SequenceAnnotationReportTest
*/
seq.addSequenceFeature(new SequenceFeature("Metal", "Desc", 0, 0, 5f,
null));
- Map minmax = new HashMap();
+
+ FeatureRendererModel fr = new FeatureRenderer(null);
+ Map minmax = fr.getMinMax();
minmax.put("Metal", new float[][] { null, new float[] { 2f, 5f } });
+
sb.setLength(0);
- sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
+ sar.createSequenceAnnotationReport(sb, seq, true, true, fr);
expected = "
SeqDesc
Metal ; Desc
Type1 ; Nonpos";
assertEquals(expected, sb.toString());
@@ -260,19 +299,20 @@ public class SequenceAnnotationReportTest
sf.setValue("linkonly", Boolean.TRUE);
seq.addSequenceFeature(sf);
sb.setLength(0);
- sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
+ sar.createSequenceAnnotationReport(sb, seq, true, true, fr);
assertEquals(expected, sb.toString()); // unchanged!
/*
- * 'clinical_significance' currently being specially included
+ * 'clinical_significance' attribute only included when
+ * used for feature colouring
*/
SequenceFeature sf2 = new SequenceFeature("Variant", "Havana", 0, 0,
5f, null);
sf2.setValue(GffConstants.CLINICAL_SIGNIFICANCE, "benign");
seq.addSequenceFeature(sf2);
sb.setLength(0);
- sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
- expected = "
SeqDesc
Metal ; Desc
Type1 ; Nonpos
Variant ; Havana; benign";
+ sar.createSequenceAnnotationReport(sb, seq, true, true, fr);
+ expected = "
SeqDesc
Metal ; Desc
Type1 ; Nonpos
Variant ; Havana";
assertEquals(expected, sb.toString());
/*
@@ -280,18 +320,24 @@ public class SequenceAnnotationReportTest
*/
seq.addDBRef(new DBRefEntry("PDB", "0", "3iu1"));
seq.addDBRef(new DBRefEntry("Uniprot", "1", "P30419"));
+
// with showDbRefs = false
sb.setLength(0);
- sar.createSequenceAnnotationReport(sb, seq, false, true, minmax);
+ sar.createSequenceAnnotationReport(sb, seq, false, true, fr);
assertEquals(expected, sb.toString()); // unchanged
- // with showDbRefs = true
+
+ // with showDbRefs = true, colour Variant features by clinical_significance
sb.setLength(0);
- sar.createSequenceAnnotationReport(sb, seq, true, true, minmax);
- expected = "
SeqDesc
UNIPROT P30419
PDB 3iu1
Metal ; Desc
Type1 ; Nonpos
Variant ; Havana; benign";
+ FeatureColourI fc = new FeatureColour(Color.green, Color.pink, 2, 3);
+ fc.setAttributeName("clinical_significance");
+ fr.setColour("Variant", fc);
+ sar.createSequenceAnnotationReport(sb, seq, true, true, fr);
+ expected = "
SeqDesc
UNIPROT P30419
PDB 3iu1
Metal ; Desc
"
+ + "Type1 ; Nonpos
Variant ; Havana; clinical_significance=benign";
assertEquals(expected, sb.toString());
// with showNonPositionalFeatures = false
sb.setLength(0);
- sar.createSequenceAnnotationReport(sb, seq, true, false, minmax);
+ sar.createSequenceAnnotationReport(sb, seq, true, false, fr);
expected = "
SeqDesc
UNIPROT P30419
PDB 3iu1";
assertEquals(expected, sb.toString());