Skip to content

Commit 00443a0

Browse files
committed
Use -log10(pvalue)*sign(NES) as default color mapping. Refactoring.
1 parent 512dc4c commit 00443a0

File tree

7 files changed

+117
-74
lines changed

7 files changed

+117
-74
lines changed

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/style/EMStyleBuilder.java

Lines changed: 60 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,12 @@
99
import java.awt.Color;
1010
import java.awt.Paint;
1111
import java.util.List;
12-
import java.util.stream.Collectors;
1312

1413
import org.baderlab.csplugins.enrichmentmap.CytoscapeServiceModule.Continuous;
1514
import org.baderlab.csplugins.enrichmentmap.CytoscapeServiceModule.Discrete;
1615
import org.baderlab.csplugins.enrichmentmap.CytoscapeServiceModule.Passthrough;
17-
import org.baderlab.csplugins.enrichmentmap.model.AbstractDataSet;
1816
import org.baderlab.csplugins.enrichmentmap.model.EMDataSet;
17+
import org.baderlab.csplugins.enrichmentmap.model.EMDataSet.Method;
1918
import org.baderlab.csplugins.enrichmentmap.model.EMSignatureDataSet;
2019
import org.baderlab.csplugins.enrichmentmap.model.EnrichmentMap;
2120
import org.baderlab.csplugins.enrichmentmap.view.util.ChartUtil;
@@ -491,77 +490,74 @@ private void setNodeBorderColors(VisualStyle vs, EMStyleOptions options) {
491490
vs.addVisualMappingFunction(dm);
492491
}
493492

494-
private void setNodeColors(VisualStyle vs, EMStyleOptions options) {
495-
String prefix = options.getAttributePrefix();
496-
List<AbstractDataSet> dataSets = options.getDataSets().stream()
497-
.filter(ds -> ds instanceof EMDataSet) // Ignore Signature Data Sets in charts
498-
.collect(Collectors.toList());
499-
500-
if (dataSets.size() == 1) {
501-
// Only 1 Data Set? Set a continuous mapping for node colour...
502-
CyNetworkView netView = options.getNetworkView();
503-
CyNetwork net = netView.getModel();
504-
505-
var logPValCol = Columns.NODE_LOG_PVALUE_MAX.with(prefix);
506-
493+
494+
private ContinuousMapping<Double,Paint> createLog10NodeColorMapping(EMStyleOptions options) {
495+
var map = options.getEnrichmentMap();
496+
var prefix = options.getAttributePrefix();
497+
498+
boolean isSingleGSEA = map.getDataSetCount() == 1 && map.getDataSetList().get(0).getMethod() == Method.GSEA;
499+
500+
String logPValCol;
501+
if(isSingleGSEA)
502+
logPValCol = Columns.NODE_LOG_PVALUE_NES.with(prefix, map.getDataSetList().get(0));
503+
else
504+
logPValCol = Columns.NODE_LOG_PVALUE_MAX.with(prefix);
505+
506+
507+
var mapping = (ContinuousMapping<Double,Paint>) cmFactory.createVisualMappingFunction(
508+
logPValCol, Double.class, BasicVisualLexicon.NODE_FILL_COLOR);
509+
510+
if(mapping != null) { // can happen in tests
511+
var network = options.getNetworkView().getModel();
507512
var colList = List.of(columnIdFactory.createColumnIdentifier(logPValCol));
508-
var range = ChartUtil.calculateGlobalRange(net, colList);
509-
var min = range.get(0);
510-
var max = range.get(1);
511-
512-
// Continuous Mapping - set node colour based on the sign of the ES score of the dataset
513-
var cm = (ContinuousMapping<Double, Paint>) cmFactory.createVisualMappingFunction(
514-
logPValCol, Double.class, BasicVisualLexicon.NODE_FILL_COLOR);
515-
516-
var color0 = ColorScheme.RD_BU_3.getColors().get(1);
517-
var color1 = ColorScheme.RD_BU_3.getColors().get(0);
513+
var range = ChartUtil.calculateGlobalRange(network, colList, true);
518514

519-
var point0 = new BoundaryRangeValues<Paint>(color0, color0, color0);
520-
var point1 = new BoundaryRangeValues<Paint>(color1, color1, color1);
515+
var colors = ColorScheme.RD_BU_3.getColors();
516+
var negColor = colors.get(2);
517+
var zeroColor = colors.get(1);
518+
var posColor = colors.get(0);
521519

522-
eventHelper.silenceEventSource(cm);
520+
var negPoint = new BoundaryRangeValues<Paint>(negColor, negColor, negColor);
521+
var zeroPoint = new BoundaryRangeValues<Paint>(zeroColor, zeroColor, zeroColor);
522+
var posPoint = new BoundaryRangeValues<Paint>(posColor, posColor, posColor);
523+
524+
eventHelper.silenceEventSource(mapping);
523525
try {
524-
cm.addPoint(min, point0);
525-
cm.addPoint(max, point1);
526+
if(isSingleGSEA) {
527+
mapping.addPoint(-range.max, negPoint);
528+
}
529+
mapping.addPoint(0.0, zeroPoint);
530+
mapping.addPoint(range.max, posPoint);
526531
} finally {
527-
eventHelper.unsilenceEventSource(cm);
532+
eventHelper.unsilenceEventSource(mapping);
528533
}
529-
530-
vs.addVisualMappingFunction(cm);
531-
532-
// Then we need to use bypass to colour the hub nodes (signature genesets)
533-
List<EMSignatureDataSet> signatureDataSets = options.getEnrichmentMap().getSignatureSetList();
534-
535-
// For "signature" nodes that were added by Post Analysis
536-
for (EMSignatureDataSet sds : signatureDataSets) {
537-
for (Long suid : sds.getNodeSuids()) {
538-
CyNode node = net.getNode(suid);
539-
if (node != null) {
540-
View<CyNode> nv = netView.getNodeView(node);
541-
if (nv != null) {
542-
nv.setLockedValue(NODE_FILL_COLOR, Colors.SIG_NODE_COLOR);
543-
}
534+
}
535+
536+
return mapping;
537+
}
538+
539+
540+
private void setNodeColors(VisualStyle vs, EMStyleOptions options) {
541+
CyNetworkView netView = options.getNetworkView();
542+
CyNetwork net = netView.getModel();
543+
544+
var mapping = createLog10NodeColorMapping(options);
545+
vs.addVisualMappingFunction(mapping);
546+
547+
// Then we need to use bypass to colour the hub nodes (signature genesets)
548+
List<EMSignatureDataSet> signatureDataSets = options.getEnrichmentMap().getSignatureSetList();
549+
550+
// For "signature" nodes that were added by Post Analysis
551+
for (EMSignatureDataSet sds : signatureDataSets) {
552+
for (Long suid : sds.getNodeSuids()) {
553+
CyNode node = net.getNode(suid);
554+
if (node != null) {
555+
View<CyNode> nv = netView.getNodeView(node);
556+
if (nv != null) {
557+
nv.setLockedValue(NODE_FILL_COLOR, Colors.SIG_NODE_COLOR);
544558
}
545559
}
546560
}
547-
548-
} else {
549-
// 2 or more Data Sets? Use simple node colours and charts...
550-
// Add mapping function for node fill color
551-
var dm = (DiscreteMapping<String, Paint>) dmFactory.createVisualMappingFunction(
552-
Columns.NODE_GS_TYPE.with(prefix, null), String.class, NODE_FILL_COLOR);
553-
554-
// Silence events fired by this mapping to prevent unnecessary style and view updates
555-
eventHelper.silenceEventSource(dm);
556-
557-
try {
558-
dm.putMapValue(Columns.NODE_GS_TYPE_ENRICHMENT, Colors.DEF_NODE_COLOR);
559-
dm.putMapValue(Columns.NODE_GS_TYPE_SIGNATURE, Colors.SIG_NODE_COLOR);
560-
} finally {
561-
eventHelper.unsilenceEventSource(dm);
562-
}
563-
564-
vs.addVisualMappingFunction(dm);
565561
}
566562
}
567563

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/style/EMStyleOptions.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import java.util.Objects;
55

66
import org.baderlab.csplugins.enrichmentmap.model.AbstractDataSet;
7+
import org.baderlab.csplugins.enrichmentmap.model.EMDataSet;
78
import org.baderlab.csplugins.enrichmentmap.model.EnrichmentMap;
89
import org.cytoscape.view.model.CyNetworkView;
910

@@ -64,4 +65,14 @@ public boolean isPostAnalysis() {
6465
public void setPostAnalysis(boolean postAnalysis) {
6566
this.postAnalysis = postAnalysis;
6667
}
68+
69+
/**
70+
* Returns the number of data sets that are not Signature data sets.
71+
*/
72+
public int getEMDataSetCount() {
73+
return (int) getDataSets()
74+
.stream()
75+
.filter(ds -> ds instanceof EMDataSet) // Ignore Signature Data Sets in charts
76+
.count();
77+
}
6778
}

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/task/ApplyEMStyleTask.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -264,10 +264,10 @@ public Map<String, Object> createChartProps() {
264264
List<CyColumnIdentifier> columns = ChartUtil.getSortedColumnIdentifiers(prefix, dataSets, columnDescriptor, columnIdFactory);
265265

266266
List<Color> colors = ChartUtil.getChartColors(chartOptions, true);
267-
List<Double> range = ChartUtil.calculateGlobalRange(options.getNetworkView().getModel(), columns);
267+
var range = ChartUtil.calculateGlobalRange(options.getNetworkView().getModel(), columns, true);
268268

269269
props.put("cy_dataColumns", columns);
270-
props.put("cy_range", range);
270+
props.put("cy_range", range.toList());
271271
props.put("cy_autoRange", false);
272272
props.put("cy_globalRange", true);
273273
props.put("cy_showItemLabels", chartOptions.isShowLabels());

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/view/legend/LegendPanel.java

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -320,11 +320,9 @@ private void updateNodeChartColorPanel(Collection<EMDataSet> dataSets) {
320320
dataSets, columnDescriptor, columnIdFactory);
321321

322322
List<Color> colors = ChartUtil.getChartColors(chartOptions, false);
323-
List<Double> range = ChartUtil.calculateGlobalRange(options.getNetworkView().getModel(), columns);
324-
double min = range.get(0) ;
325-
double max = range.get(1);
323+
var range = ChartUtil.calculateGlobalRange(options.getNetworkView().getModel(), columns, true);
326324

327-
String posMaxLabel = max > 0 ? String.format("%.2f", max) : "N/A";
325+
String posMaxLabel = range.max > 0 ? String.format("%.2f", range.max) : "N/A";
328326
Color posMaxColor;
329327
Color posMinColor;
330328
if(data == ChartData.NES_VALUE) {
@@ -354,7 +352,7 @@ private void updateNodeChartColorPanel(Collection<EMDataSet> dataSets) {
354352

355353

356354
if(data == ChartData.NES_VALUE || data == ChartData.NES_SIG || data == ChartData.LOG10_PVAL_NES) { // need to show negative range
357-
String negMinLabel = min < 0 ? String.format("%.2f", min) : "N/A";
355+
String negMinLabel = range.min < 0 ? String.format("%.2f", range.min) : "N/A";
358356
Color negMaxColor = colors.get(colors.size()-1);
359357
Color negMinColor = colors.get(colors.size()/2);
360358
chartNegLegend = new ColorLegendPanel(negMinColor, negMaxColor, "0", negMinLabel, false);

EnrichmentMapPlugin/src/main/java/org/baderlab/csplugins/enrichmentmap/view/util/ChartUtil.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,7 @@ public static List<EMDataSet> sortDataSets(Collection<EMDataSet> dataSets) {
9999
* @return List whose first item is the minimum value of the range, and whose second item is the maximum value.
100100
*/
101101
@SuppressWarnings("unchecked")
102-
public static List<Double> calculateGlobalRange(CyNetwork network, List<CyColumnIdentifier> dataColumns) {
102+
public static Range calculateGlobalRange(CyNetwork network, List<CyColumnIdentifier> dataColumns, boolean includeZero) {
103103
List<CyNode> nodes = network.getNodeList();
104104

105105
if (!nodes.isEmpty()) {
@@ -137,11 +137,15 @@ else if (row.isSet(column.getName()))
137137
}
138138

139139
if (min != Double.POSITIVE_INFINITY && max != Double.NEGATIVE_INFINITY) {
140-
return List.of(min, max);
140+
if(includeZero) {
141+
return new Range(Math.min(min, 0), Math.max(0, max));
142+
}
143+
144+
return new Range(min, max);
141145
}
142146
}
143147

144-
return List.of(0.0, 0.0);
148+
return new Range(0.0, 0.0);
145149
}
146150

147151

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
package org.baderlab.csplugins.enrichmentmap.view.util;
2+
3+
import java.util.List;
4+
5+
public class Range {
6+
7+
public final double min;
8+
public final double max;
9+
10+
public Range(double min, double max) {
11+
assert min <= max;
12+
this.min = min;
13+
this.max = max;
14+
}
15+
16+
public List<Double> toList() {
17+
return List.of(min, max);
18+
}
19+
20+
@Override
21+
public String toString() {
22+
return "Range[min=" + min + ", max=" + max + "]";
23+
}
24+
25+
}

EnrichmentMapPlugin/src/test/java/org/baderlab/csplugins/enrichmentmap/style/ApplyStyleTest.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.baderlab.csplugins.enrichmentmap.style.EMStyleBuilder.Columns;
1919
import org.baderlab.csplugins.enrichmentmap.style.EMStyleBuilder.StyleUpdateScope;
2020
import org.cytoscape.model.CyEdge;
21+
import org.cytoscape.model.CyNetwork;
2122
import org.cytoscape.model.CyNode;
2223
import org.cytoscape.view.model.CyNetworkView;
2324
import org.cytoscape.view.model.VisualLexicon;
@@ -26,6 +27,8 @@
2627
import org.cytoscape.view.presentation.customgraphics.CyCustomGraphics2;
2728
import org.cytoscape.view.presentation.property.LineTypeVisualProperty;
2829
import org.cytoscape.view.presentation.property.NodeShapeVisualProperty;
30+
import org.cytoscape.view.presentation.property.values.CyColumnIdentifier;
31+
import org.cytoscape.view.presentation.property.values.CyColumnIdentifierFactory;
2932
import org.cytoscape.view.presentation.property.values.LineType;
3033
import org.cytoscape.view.presentation.property.values.NodeShape;
3134
import org.cytoscape.view.vizmap.VisualMappingFunctionFactory;
@@ -85,6 +88,11 @@ protected void configureTest() {
8588
when(em.getDataSetCount()).thenReturn(2);
8689

8790
bind(EnrichmentMap.class).toInstance(em);
91+
92+
// CyColumnIdentifierFactory columnIdFactory;
93+
var columnIdFactory = mock(CyColumnIdentifierFactory.class);
94+
bind(CyColumnIdentifierFactory.class).toInstance(columnIdFactory);
95+
when(columnIdFactory.createColumnIdentifier(any())).thenReturn(mock(CyColumnIdentifier.class));
8896
}
8997
}
9098

@@ -132,6 +140,7 @@ public void applyStyle_ALL(
132140
// Create the style
133141
VisualStyle vs = mock(VisualStyle.class);
134142
CyNetworkView netView = mock(CyNetworkView.class);
143+
when(netView.getModel()).thenReturn(mock(CyNetwork.class));
135144
CyCustomGraphics2 chart = mock(CyCustomGraphics2.class);
136145
EMStyleOptions options = new EMStyleOptions(netView, em);
137146

0 commit comments

Comments
 (0)